1 #include "kernel/kernel.h"
2 #include "kernel/clock.h"
3 #include <sys/types.h>
4 #include <machine/cpu.h>
5 #include <minix/board.h>
6 #include <minix/mmio.h>
7 #include <assert.h>
8 #include <io.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include "arch_proto.h"
12 #include "bsp_timer.h"
13 #include "omap_timer_registers.h"
14 #include "omap_intr_registers.h"
15 #include "bsp_intr.h"
16
17 /* interrupt handler hook */
18 static irq_hook_t omap3_timer_hook;
19 static u64_t high_frc;
20
21 struct omap_timer_registers;
22
23 struct omap_timer
24 {
25 vir_bytes base;
26 int irq_nr;
27 struct omap_timer_registers *regs;
28 };
29
30 struct omap_timer_registers
31 {
32 vir_bytes TIDR;
33 vir_bytes TIOCP_CFG;
34 vir_bytes TISTAT;
35 vir_bytes TISR;
36 vir_bytes TIER;
37 vir_bytes TWER;
38 vir_bytes TCLR;
39 vir_bytes TCRR;
40 vir_bytes TLDR;
41 vir_bytes TTGR;
42 vir_bytes TWPS;
43 vir_bytes TMAR;
44 vir_bytes TCAR1;
45 vir_bytes TSICR;
46 vir_bytes TCAR2;
47 vir_bytes TPIR;
48 vir_bytes TNIR;
49 vir_bytes TCVR;
50 vir_bytes TOCR;
51 vir_bytes TOWR;
52
53 };
54
55 static struct omap_timer_registers regs_v1 = {
56 .TIDR = OMAP3_TIMER_TIDR,
57 .TIOCP_CFG = OMAP3_TIMER_TIOCP_CFG,
58 .TISTAT = OMAP3_TIMER_TISTAT,
59 .TISR = OMAP3_TIMER_TISR,
60 .TIER = OMAP3_TIMER_TIER,
61 .TWER = OMAP3_TIMER_TWER,
62 .TCLR = OMAP3_TIMER_TCLR,
63 .TCRR = OMAP3_TIMER_TCRR,
64 .TLDR = OMAP3_TIMER_TLDR,
65 .TTGR = OMAP3_TIMER_TTGR,
66 .TWPS = OMAP3_TIMER_TWPS,
67 .TMAR = OMAP3_TIMER_TMAR,
68 .TCAR1 = OMAP3_TIMER_TCAR1,
69 .TSICR = OMAP3_TIMER_TSICR,
70 .TCAR2 = OMAP3_TIMER_TCAR2,
71 .TPIR = OMAP3_TIMER_TPIR,
72 .TNIR = OMAP3_TIMER_TNIR,
73 .TCVR = OMAP3_TIMER_TCVR,
74 .TOCR = OMAP3_TIMER_TOCR,
75 .TOWR = OMAP3_TIMER_TOWR,
76 };
77
78 /* AM335X has a different ip block for the non
79 1ms timers */
80 static struct omap_timer_registers regs_v2 = {
81 .TIDR = AM335X_TIMER_TIDR,
82 .TIOCP_CFG = AM335X_TIMER_TIOCP_CFG,
83 .TISTAT = AM335X_TIMER_IRQSTATUS_RAW,
84 .TISR = AM335X_TIMER_IRQSTATUS,
85 .TIER = AM335X_TIMER_IRQENABLE_SET,
86 .TWER = AM335X_TIMER_IRQWAKEEN,
87 .TCLR = AM335X_TIMER_TCLR,
88 .TCRR = AM335X_TIMER_TCRR,
89 .TLDR = AM335X_TIMER_TLDR,
90 .TTGR = AM335X_TIMER_TTGR,
91 .TWPS = AM335X_TIMER_TWPS,
92 .TMAR = AM335X_TIMER_TMAR,
93 .TCAR1 = AM335X_TIMER_TCAR1,
94 .TSICR = AM335X_TIMER_TSICR,
95 .TCAR2 = AM335X_TIMER_TCAR2,
96 .TPIR = -1, /* UNDEF */
97 .TNIR = -1, /* UNDEF */
98 .TCVR = -1, /* UNDEF */
99 .TOCR = -1, /* UNDEF */
100 .TOWR = -1 /* UNDEF */
101 };
102
103 static struct omap_timer dm37xx_timer = {
104 .base = OMAP3_GPTIMER1_BASE,
105 .irq_nr = OMAP3_GPT1_IRQ,
106 .regs = ®s_v1
107 };
108
109 /* free running timer */
110 static struct omap_timer dm37xx_fr_timer = {
111 .base = OMAP3_GPTIMER10_BASE,
112 .irq_nr = OMAP3_GPT10_IRQ,
113 .regs = ®s_v1
114 };
115
116 /* normal timer */
117 static struct omap_timer am335x_timer = {
118 .base = AM335X_DMTIMER1_1MS_BASE,
119 .irq_nr = AM335X_INT_TINT1_1MS,
120 .regs = ®s_v1
121 };
122
123 /* free running timer */
124 static struct omap_timer am335x_fr_timer = {
125 .base = AM335X_DMTIMER7_BASE,
126 .irq_nr = AM335X_INT_TINT7,
127 .regs = ®s_v2
128 };
129
130 static struct omap_timer *timer;
131 static struct omap_timer *fr_timer;
132
133 static int done = 0;
134
135 int
bsp_register_timer_handler(const irq_handler_t handler)136 bsp_register_timer_handler(const irq_handler_t handler)
137 {
138 /* Initialize the CLOCK's interrupt hook. */
139 omap3_timer_hook.proc_nr_e = NONE;
140 omap3_timer_hook.irq = timer->irq_nr;
141
142 put_irq_handler(&omap3_timer_hook, timer->irq_nr, handler);
143 /* only unmask interrupts after registering */
144 bsp_irq_unmask(timer->irq_nr);
145
146 return 0;
147 }
148
149 /* meta data for remapping */
150 static kern_phys_map timer_phys_map;
151 static kern_phys_map fr_timer_phys_map;
152 static kern_phys_map fr_timer_user_phys_map; /* struct for when the free */
153 /* running timer is mapped to */
154 /* userland */
155
156 /* callback for when the free running clock gets mapped */
157 int
kern_phys_fr_user_mapped(vir_bytes id,phys_bytes address)158 kern_phys_fr_user_mapped(vir_bytes id, phys_bytes address)
159 {
160 /* the only thing we need to do at this stage is to set the address */
161 /* in the kerninfo struct */
162 if (BOARD_IS_BBXM(machine.board_id)) {
163 arm_frclock.tcrr = address + OMAP3_TIMER_TCRR;
164 arm_frclock.hz = 1625000;
165 } else if (BOARD_IS_BB(machine.board_id)) {
166 arm_frclock.tcrr = address + AM335X_TIMER_TCRR;
167 arm_frclock.hz = 1500000;
168 }
169 return 0;
170 }
171
172 void
omap3_frclock_init(void)173 omap3_frclock_init(void)
174 {
175 u32_t tisr;
176
177 /* enable the clock */
178 if (BOARD_IS_BBXM(machine.board_id)) {
179 fr_timer = &dm37xx_fr_timer;
180
181 kern_phys_map_ptr(fr_timer->base, ARM_PAGE_SIZE,
182 VMMF_UNCACHED | VMMF_WRITE, &fr_timer_phys_map,
183 (vir_bytes) & fr_timer->base);
184
185 /* the timer is also mapped in user space hence the this */
186 /* second mapping and callback to set kerninfo frclock_tcrr */
187 kern_req_phys_map(fr_timer->base, ARM_PAGE_SIZE,
188 VMMF_UNCACHED | VMMF_USER,
189 &fr_timer_user_phys_map, kern_phys_fr_user_mapped, 0);
190
191 /* Stop timer */
192 mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
193 OMAP3_TCLR_ST);
194
195 /* Use functional clock source for GPTIMER10 */
196 mmio_set(OMAP3_CM_CLKSEL_CORE, OMAP3_CLKSEL_GPT10);
197
198 /* Scale timer down to 13/8 = 1.625 Mhz to roughly get
199 * microsecond ticks */
200 /* The scale is computed as 2^(PTV+1). So if PTV == 2, we get
201 * 2^3 = 8. */
202 mmio_set(fr_timer->base + fr_timer->regs->TCLR,
203 (2 << OMAP3_TCLR_PTV));
204 } else if (BOARD_IS_BB(machine.board_id)) {
205 fr_timer = &am335x_fr_timer;
206 kern_phys_map_ptr(fr_timer->base, ARM_PAGE_SIZE,
207 VMMF_UNCACHED | VMMF_WRITE,
208 &fr_timer_phys_map, (vir_bytes) & fr_timer->base);
209
210 /* the timer is also mapped in user space hence the this */
211 /* second mapping and callback to set kerninfo frclock_tcrr */
212 kern_req_phys_map(fr_timer->base, ARM_PAGE_SIZE,
213 VMMF_UNCACHED | VMMF_USER,
214 &fr_timer_user_phys_map, kern_phys_fr_user_mapped, 0);
215 /* Disable the module and wait for the module to be disabled */
216 set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
217 CM_MODULEMODE_DISABLED);
218 while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
219 != CM_CLKCTRL_IDLEST_DISABLE);
220
221 set32(CLKSEL_TIMER7_CLK, CLKSEL_TIMER7_CLK_SEL_MASK,
222 CLKSEL_TIMER7_CLK_SEL_SEL2);
223 while ((read32(CLKSEL_TIMER7_CLK) & CLKSEL_TIMER7_CLK_SEL_MASK)
224 != CLKSEL_TIMER7_CLK_SEL_SEL2);
225
226 /* enable the module and wait for the module to be ready */
227 set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
228 CM_MODULEMODE_ENABLE);
229 while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
230 != CM_CLKCTRL_IDLEST_FUNC);
231
232 /* Stop timer */
233 mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
234 OMAP3_TCLR_ST);
235
236 /* 24Mhz / 16 = 1.5 Mhz */
237 mmio_set(fr_timer->base + fr_timer->regs->TCLR,
238 (3 << OMAP3_TCLR_PTV));
239 }
240
241 /* Start and auto-reload at 0 */
242 mmio_write(fr_timer->base + fr_timer->regs->TLDR, 0x0);
243 mmio_write(fr_timer->base + fr_timer->regs->TCRR, 0x0);
244
245 /* Set up overflow interrupt */
246 tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
247 OMAP3_TISR_TCAR_IT_FLAG;
248 /* Clear interrupt status */
249 mmio_write(fr_timer->base + fr_timer->regs->TISR, tisr);
250 mmio_write(fr_timer->base + fr_timer->regs->TIER,
251 OMAP3_TIER_OVF_IT_ENA);
252
253 /* Start timer */
254 mmio_set(fr_timer->base + fr_timer->regs->TCLR,
255 OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST |
256 OMAP3_TCLR_PRE);
257 done = 1;
258 }
259
260 void
omap3_frclock_stop(void)261 omap3_frclock_stop(void)
262 {
263 mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST);
264 }
265
266 void
bsp_timer_init(unsigned freq)267 bsp_timer_init(unsigned freq)
268 {
269 /* we only support 1ms resolution */
270 u32_t tisr;
271 if (BOARD_IS_BBXM(machine.board_id)) {
272 timer = &dm37xx_timer;
273 kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE,
274 VMMF_UNCACHED | VMMF_WRITE,
275 &timer_phys_map, (vir_bytes) & timer->base);
276 /* Stop timer */
277 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
278
279 /* Use 32 KHz clock source for GPTIMER1 */
280 mmio_clear(OMAP3_CM_CLKSEL_WKUP, OMAP3_CLKSEL_GPT1);
281 } else if (BOARD_IS_BB(machine.board_id)) {
282 timer = &am335x_timer;
283 kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE,
284 VMMF_UNCACHED | VMMF_WRITE,
285 &timer_phys_map, (vir_bytes) & timer->base);
286 /* disable the module and wait for the module to be disabled */
287 set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
288 CM_MODULEMODE_DISABLED);
289 while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
290 != CM_CLKCTRL_IDLEST_DISABLE);
291
292 set32(CLKSEL_TIMER1MS_CLK, CLKSEL_TIMER1MS_CLK_SEL_MASK,
293 CLKSEL_TIMER1MS_CLK_SEL_SEL2);
294 while ((read32(CLKSEL_TIMER1MS_CLK) &
295 CLKSEL_TIMER1MS_CLK_SEL_MASK) !=
296 CLKSEL_TIMER1MS_CLK_SEL_SEL2);
297
298 /* enable the module and wait for the module to be ready */
299 set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
300 CM_MODULEMODE_ENABLE);
301 while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
302 != CM_CLKCTRL_IDLEST_FUNC);
303
304 /* Stop timer */
305 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
306 }
307
308 /* Use 1-ms tick mode for GPTIMER1 TRM 16.2.4.2.1 */
309 mmio_write(timer->base + timer->regs->TPIR, 232000);
310 mmio_write(timer->base + timer->regs->TNIR, -768000);
311 mmio_write(timer->base + timer->regs->TLDR,
312 0xffffffff - (32768 / freq) + 1);
313 mmio_write(timer->base + timer->regs->TCRR,
314 0xffffffff - (32768 / freq) + 1);
315
316 /* Set up overflow interrupt */
317 tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
318 OMAP3_TISR_TCAR_IT_FLAG;
319 /* Clear interrupt status */
320 mmio_write(timer->base + timer->regs->TISR, tisr);
321 mmio_write(timer->base + timer->regs->TIER, OMAP3_TIER_OVF_IT_ENA);
322
323 /* Start timer */
324 mmio_set(timer->base + timer->regs->TCLR,
325 OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
326 /* also initilize the free runnning timer */
327 omap3_frclock_init();
328 }
329
330 void
bsp_timer_stop(void)331 bsp_timer_stop(void)
332 {
333 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
334 }
335
336 static u32_t
read_frc(void)337 read_frc(void)
338 {
339 if (done == 0) {
340 return 0;
341 }
342 return mmio_read(fr_timer->base + fr_timer->regs->TCRR);
343 }
344
345 /*
346 * Check if the free running clock has overflown and
347 * increase the high free running clock counter if
348 * so. This method takes the current timer value as
349 * parameter to ensure the overflow check is done
350 * on the current timer value.
351 *
352 * To compose the current timer value (64 bits) you
353 * need to follow the following sequence:
354 * read the current timer value.
355 * call the overflow check
356 * compose the 64 bits time based on the current timer value
357 * and high_frc.
358 */
359 static void
frc_overflow_check(u32_t cur_frc)360 frc_overflow_check(u32_t cur_frc)
361 {
362 static int prev_frc_valid;
363 static u32_t prev_frc;
364 if (prev_frc_valid && prev_frc > cur_frc) {
365 high_frc++;
366 }
367 prev_frc = cur_frc;
368 prev_frc_valid = 1;
369 }
370
371 void
bsp_timer_int_handler(void)372 bsp_timer_int_handler(void)
373 {
374 /* Clear all interrupts */
375 u32_t tisr, now;
376
377 /* when the kernel itself is running interrupts are disabled. We
378 * should therefore also read the overflow counter to detect this as
379 * to not miss events. */
380 tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
381 OMAP3_TISR_TCAR_IT_FLAG;
382 mmio_write(timer->base + timer->regs->TISR, tisr);
383
384 now = read_frc();
385 frc_overflow_check(now);
386 }
387
388 /* Use the free running clock as TSC */
389 void
read_tsc_64(u64_t * t)390 read_tsc_64(u64_t * t)
391 {
392 u32_t now;
393 now = read_frc();
394 frc_overflow_check(now);
395 *t = (u64_t) now + (high_frc << 32);
396 }
397