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 minix_kerninfo.minix_frclock_tcrr = address + OMAP3_TIMER_TCRR; 164 minix_kerninfo.minix_arm_frclock_hz = 1625000; 165 } else if (BOARD_IS_BB(machine.board_id)) { 166 minix_kerninfo.minix_frclock_tcrr = 167 address + AM335X_TIMER_TCRR; 168 minix_kerninfo.minix_arm_frclock_hz = 1500000; 169 } 170 return 0; 171 } 172 173 void 174 omap3_frclock_init(void) 175 { 176 u32_t tisr; 177 178 /* enable the clock */ 179 if (BOARD_IS_BBXM(machine.board_id)) { 180 fr_timer = &dm37xx_fr_timer; 181 182 kern_phys_map_ptr(fr_timer->base, ARM_PAGE_SIZE, 183 VMMF_UNCACHED | VMMF_WRITE, &fr_timer_phys_map, 184 (vir_bytes) & fr_timer->base); 185 186 /* the timer is also mapped in user space hence the this */ 187 /* second mapping and callback to set kerninfo frclock_tcrr */ 188 kern_req_phys_map(fr_timer->base, ARM_PAGE_SIZE, 189 VMMF_UNCACHED | VMMF_USER, 190 &fr_timer_user_phys_map, kern_phys_fr_user_mapped, 0); 191 192 /* Stop timer */ 193 mmio_clear(fr_timer->base + fr_timer->regs->TCLR, 194 OMAP3_TCLR_ST); 195 196 /* Use functional clock source for GPTIMER10 */ 197 mmio_set(OMAP3_CM_CLKSEL_CORE, OMAP3_CLKSEL_GPT10); 198 199 /* Scale timer down to 13/8 = 1.625 Mhz to roughly get 200 * microsecond ticks */ 201 /* The scale is computed as 2^(PTV+1). So if PTV == 2, we get 202 * 2^3 = 8. */ 203 mmio_set(fr_timer->base + fr_timer->regs->TCLR, 204 (2 << OMAP3_TCLR_PTV)); 205 } else if (BOARD_IS_BB(machine.board_id)) { 206 fr_timer = &am335x_fr_timer; 207 kern_phys_map_ptr(fr_timer->base, ARM_PAGE_SIZE, 208 VMMF_UNCACHED | VMMF_WRITE, 209 &fr_timer_phys_map, (vir_bytes) & fr_timer->base); 210 211 /* the timer is also mapped in user space hence the this */ 212 /* second mapping and callback to set kerninfo frclock_tcrr */ 213 kern_req_phys_map(fr_timer->base, ARM_PAGE_SIZE, 214 VMMF_UNCACHED | VMMF_USER, 215 &fr_timer_user_phys_map, kern_phys_fr_user_mapped, 0); 216 /* Disable the module and wait for the module to be disabled */ 217 set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK, 218 CM_MODULEMODE_DISABLED); 219 while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST) 220 != CM_CLKCTRL_IDLEST_DISABLE); 221 222 set32(CLKSEL_TIMER7_CLK, CLKSEL_TIMER7_CLK_SEL_MASK, 223 CLKSEL_TIMER7_CLK_SEL_SEL2); 224 while ((read32(CLKSEL_TIMER7_CLK) & CLKSEL_TIMER7_CLK_SEL_MASK) 225 != CLKSEL_TIMER7_CLK_SEL_SEL2); 226 227 /* enable the module and wait for the module to be ready */ 228 set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK, 229 CM_MODULEMODE_ENABLE); 230 while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST) 231 != CM_CLKCTRL_IDLEST_FUNC); 232 233 /* Stop timer */ 234 mmio_clear(fr_timer->base + fr_timer->regs->TCLR, 235 OMAP3_TCLR_ST); 236 237 /* 24Mhz / 16 = 1.5 Mhz */ 238 mmio_set(fr_timer->base + fr_timer->regs->TCLR, 239 (3 << OMAP3_TCLR_PTV)); 240 } 241 242 /* Start and auto-reload at 0 */ 243 mmio_write(fr_timer->base + fr_timer->regs->TLDR, 0x0); 244 mmio_write(fr_timer->base + fr_timer->regs->TCRR, 0x0); 245 246 /* Set up overflow interrupt */ 247 tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | 248 OMAP3_TISR_TCAR_IT_FLAG; 249 /* Clear interrupt status */ 250 mmio_write(fr_timer->base + fr_timer->regs->TISR, tisr); 251 mmio_write(fr_timer->base + fr_timer->regs->TIER, 252 OMAP3_TIER_OVF_IT_ENA); 253 254 /* Start timer */ 255 mmio_set(fr_timer->base + fr_timer->regs->TCLR, 256 OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST | 257 OMAP3_TCLR_PRE); 258 done = 1; 259 } 260 261 void 262 omap3_frclock_stop() 263 { 264 mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST); 265 } 266 267 void 268 bsp_timer_init(unsigned freq) 269 { 270 /* we only support 1ms resolution */ 271 u32_t tisr; 272 if (BOARD_IS_BBXM(machine.board_id)) { 273 timer = &dm37xx_timer; 274 kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE, 275 VMMF_UNCACHED | VMMF_WRITE, 276 &timer_phys_map, (vir_bytes) & timer->base); 277 /* Stop timer */ 278 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); 279 280 /* Use 32 KHz clock source for GPTIMER1 */ 281 mmio_clear(OMAP3_CM_CLKSEL_WKUP, OMAP3_CLKSEL_GPT1); 282 } else if (BOARD_IS_BB(machine.board_id)) { 283 timer = &am335x_timer; 284 kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE, 285 VMMF_UNCACHED | VMMF_WRITE, 286 &timer_phys_map, (vir_bytes) & timer->base); 287 /* disable the module and wait for the module to be disabled */ 288 set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK, 289 CM_MODULEMODE_DISABLED); 290 while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST) 291 != CM_CLKCTRL_IDLEST_DISABLE); 292 293 set32(CLKSEL_TIMER1MS_CLK, CLKSEL_TIMER1MS_CLK_SEL_MASK, 294 CLKSEL_TIMER1MS_CLK_SEL_SEL2); 295 while ((read32(CLKSEL_TIMER1MS_CLK) & 296 CLKSEL_TIMER1MS_CLK_SEL_MASK) != 297 CLKSEL_TIMER1MS_CLK_SEL_SEL2); 298 299 /* enable the module and wait for the module to be ready */ 300 set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK, 301 CM_MODULEMODE_ENABLE); 302 while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST) 303 != CM_CLKCTRL_IDLEST_FUNC); 304 305 /* Stop timer */ 306 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); 307 } 308 309 /* Use 1-ms tick mode for GPTIMER1 TRM 16.2.4.2.1 */ 310 mmio_write(timer->base + timer->regs->TPIR, 232000); 311 mmio_write(timer->base + timer->regs->TNIR, -768000); 312 mmio_write(timer->base + timer->regs->TLDR, 313 0xffffffff - (32768 / freq) + 1); 314 mmio_write(timer->base + timer->regs->TCRR, 315 0xffffffff - (32768 / freq) + 1); 316 317 /* Set up overflow interrupt */ 318 tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | 319 OMAP3_TISR_TCAR_IT_FLAG; 320 /* Clear interrupt status */ 321 mmio_write(timer->base + timer->regs->TISR, tisr); 322 mmio_write(timer->base + timer->regs->TIER, OMAP3_TIER_OVF_IT_ENA); 323 324 /* Start timer */ 325 mmio_set(timer->base + timer->regs->TCLR, 326 OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST); 327 /* also initilize the free runnning timer */ 328 omap3_frclock_init(); 329 } 330 331 void 332 bsp_timer_stop() 333 { 334 mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); 335 } 336 337 static u32_t 338 read_frc(void) 339 { 340 if (done == 0) { 341 return 0; 342 } 343 return mmio_read(fr_timer->base + fr_timer->regs->TCRR); 344 } 345 346 /* 347 * Check if the free running clock has overflown and 348 * increase the high free running clock counter if 349 * so. This method takes the current timer value as 350 * parameter to ensure the overflow check is done 351 * on the current timer value. 352 * 353 * To compose the current timer value (64 bits) you 354 * need to follow the following sequence: 355 * read the current timer value. 356 * call the overflow check 357 * compose the 64 bits time based on the current timer value 358 * and high_frc. 359 */ 360 static void 361 frc_overflow_check(u32_t cur_frc) 362 { 363 static int prev_frc_valid; 364 static u32_t prev_frc; 365 if (prev_frc_valid && prev_frc > cur_frc) { 366 high_frc++; 367 } 368 prev_frc = cur_frc; 369 prev_frc_valid = 1; 370 } 371 372 void 373 bsp_timer_int_handler() 374 { 375 /* Clear all interrupts */ 376 u32_t tisr, now; 377 378 /* when the kernel itself is running interrupts are disabled. We 379 * should therefore also read the overflow counter to detect this as 380 * to not miss events. */ 381 tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | 382 OMAP3_TISR_TCAR_IT_FLAG; 383 mmio_write(timer->base + timer->regs->TISR, tisr); 384 385 now = read_frc(); 386 frc_overflow_check(now); 387 } 388 389 /* Use the free running clock as TSC */ 390 void 391 read_tsc_64(u64_t * t) 392 { 393 u32_t now; 394 now = read_frc(); 395 frc_overflow_check(now); 396 *t = (u64_t) now + (high_frc << 32); 397 } 398