82c801c2cc25f6a6b7d1e6886b7f848748725912
1 /*
2 * tim64.c : enable use of timer64 from user space
3 * (using 64 bit mode)
4 * TIMER 6
5 **************************************************************
6 * FILE: tim64.c
7 *
8 * DESCRIPTION: tim64 peripheral driver for user space transport
9 * library
10 *
11 * REVISION HISTORY: rev 0.0.1
12 *
13 * Copyright (c) Texas Instruments Incorporated 2010-2011
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the
25 * distribution.
26 *
27 * Neither the name of Texas Instruments Incorporated nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 */
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <string.h>
49 #include <errno.h>
50 #include <signal.h>
51 #include <fcntl.h>
52 #include <ctype.h>
53 #include <termios.h>
54 #include <sys/types.h>
55 #include <sys/mman.h>
56 #include "netapi_timer.h"
58 /* timing */
59 static inline unsigned long timing_start(void)
60 {
61 volatile int vval;
62 //read clock
63 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(vval));
64 return vval;
65 }
66 static inline unsigned long timing_stop(void)
67 {
68 volatile int vval2;
69 //read clock
70 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(vval2));
71 return vval2;
72 }
76 #define MAP_SIZE 4096UL
77 #define MAP_MASK (MAP_SIZE - 1)
78 //this is for timer 6
79 #define T64BASE_6 (void *)0x02260000
80 volatile unsigned long * t64_virt_addr;
81 static unsigned long tv_lo;
82 static unsigned long tv_hi;
84 //read
85 static unsigned long long read_t64(void)
86 {
87 volatile unsigned long long t1;
88 volatile unsigned long long t2;
89 unsigned long long val;
90 t1 = t64_virt_addr[0x10/4]; //lo
91 t2 = t64_virt_addr[0x14/4]; //hi
93 val = ((unsigned long long) t2) <<32 | t1;
94 return val;
96 }
98 //claibrate
99 static unsigned int t64_cpu_cycle_per_tick=0;
100 unsigned int cpu_cycles_sec=983040000;
101 unsigned long t64_ticks_sec(void)
102 {
103 if (t64_cpu_cycle_per_tick)
104 return ( cpu_cycles_sec/t64_cpu_cycle_per_tick); //ticks per/sec
105 else return 166666666;
107 }
108 static int t64_calibrate(int n)
109 {
110 volatile unsigned long t1;
111 volatile unsigned long t2;
112 volatile unsigned long long t164;
113 volatile unsigned long long t264;
114 int i;
115 volatile int s;
116 t1=timing_start();
117 t164=read_t64();
119 sleep(1);
120 #if 0
121 for(i=0;i<n;i++)
122 {
123 s+=t164*20; s=s*(2+i);
124 }
125 #endif
126 t264=read_t64();
127 t2=timing_stop();
128 t64_cpu_cycle_per_tick = (unsigned long) ((t2-t1)/(t264-t164));
129 printf("calib - n=%d t2-t1=%lu t264-t164=%llu ccpt=%ld tps=%ld\n",
130 n, t2-t1, t264-t164, t64_cpu_cycle_per_tick, t64_ticks_sec());
132 }
135 /*********************************
136 * memory map t64 into user space
137 * input: pass in fd for /dev/mem
138 **********************************/
139 int t64_memmap(int fd)
140 {
141 off_t t64_base= (off_t) T64BASE_6;
142 void * map_base;
143 int op;
144 volatile unsigned long t1;
145 volatile unsigned long t2;
146 unsigned long long blah;
149 /* Map one page */
150 map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, t64_base & ~MAP_MASK);
151 if(map_base == (void *) -1) exit(-99);
152 printf("tim64>mapbase=Memory mapped at address %p.\n", map_base);
153 fflush(stdout);
155 t64_virt_addr = (long *) map_base + (t64_base & MAP_MASK);
156 printf("tim64>t64_virt_addr: Memory mapped at address %p.\n", t64_virt_addr);
157 fflush(stdout);
158 return 1;
159 }
162 /*********************************
163 * start the timer64
164 ***********************************/
165 int t64_start(void)
166 {
167 t64_virt_addr[0x24/4]= 0x00;
168 t64_virt_addr[0x10/4]= 0x00;
169 t64_virt_addr[0x14/4]= 0x00;
170 t64_virt_addr[0x18/4]= 0xffffffff;
171 t64_virt_addr[0x1c/4]= 0xffffffff;
172 t64_virt_addr[0x20/4]= 0x80;
173 t64_virt_addr[0x24/4]= 0x03; //go
174 t64_calibrate(100000);
175 return 1;
176 }
179 #ifdef TEST_DRIVER
180 int main(int argc, char **argv) {
181 int fd;
182 off_t t64_base= (off_t) T64BASE_6;
183 void * map_base;
184 int op;
185 volatile unsigned long t1;
186 volatile unsigned long t2;
187 unsigned long long blah;
189 if(argc < 2) {
190 fprintf(stderr, "Usage: tim64 start|stop|read \n"
191 );
192 exit(1);
193 }
194 if (!strcmp(argv[1],"start")) op=0;
195 else if (!strcmp(argv[1],"stop")) op =1;
196 else if (!strcmp(argv[1],"read")) op =2;
197 else { fprintf(stderr, "Usage: tim64 start|stop|read \n"
198 );
199 exit(1);
200 }
203 if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) exit(-99);
204 printf("/dev/mem opened.\n");
205 fflush(stdout);
207 /* Map one page */
208 map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, t64_base & ~MAP_MASK);
209 if(map_base == (void *) -1) exit(-99);
210 printf("mapbase=Memory mapped at address %p.\n", map_base);
211 fflush(stdout);
213 t64_virt_addr = (long *) map_base + (t64_base & MAP_MASK);
214 printf("t64_virt_ddr: Memory mapped at address %p.\n", t64_virt_addr);
215 fflush(stdout);
217 switch(op)
218 {
219 case(0):
220 default:
221 //start
222 t64_virt_addr[0x24/4]= 0x00;
223 t64_virt_addr[0x10/4]= 0x00;
224 t64_virt_addr[0x14/4]= 0x00;
225 t64_virt_addr[0x18/4]= 0xffffffff;
226 t64_virt_addr[0x1c/4]= 0xffffffff;
227 t64_virt_addr[0x20/4]= 0x80;
228 t64_virt_addr[0x24/4]= 0x03; //go
229 t64_calibrate(100000);
230 break;
231 case(1):
232 //stop
233 t64_virt_addr[0x24/4]= 0x00;
234 break;
235 case(2):
236 //read
237 tv_lo= t64_virt_addr[0x10/4];
238 tv_hi= t64_virt_addr[0x14/4];
239 t1=timing_start();
240 blah = read_t64();
241 t2=timing_stop();
243 printf("t64 = %x%x %llx (read_t64 takes %d ticks)\n",tv_hi,tv_lo,blah, t2-t1);
244 break;
245 }
246 if(munmap(map_base, MAP_SIZE) == -1) exit(-99);
247 close(fd);
248 return 0;
249 }
250 #endif