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 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 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 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 261 omap3_frclock_stop() 262 { 263 mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST); 264 } 265 266 void 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 331 bsp_timer_stop() 332 { 333 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); 334 } 335 336 static u32_t 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 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 372 bsp_timer_int_handler() 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 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