void init_qtime_ixp23xx() { struct qtime_entry *qtime = alloc_qtime(); /* * Map the timer registers */ ixp23xx_timer_base = startup_io_map(IXP23XX_OST_SIZE, IXP23XX_OST_BASE); /* * Set the timer with maximum countdown, auto reload. The two least significant * bits of the reload register are actually control bits, and are written as zero * when loading the count value. Bit one selects one-shot (1) or Auto-reload (0), * and bit 0 starts the timer running. */ out32(ixp23xx_timer_base + IXP23XX_OST_TIM0_RL, 0xfffffffc); /* clear any pending interrupt on the timer */ out32(ixp23xx_timer_base + IXP23XX_OST_STS, 0x01); timer_start = timer_start_ixp23xx; timer_diff = timer_diff_ixp23xx; qtime->intr = 3; qtime->timer_rate = IXP23XX_CLOCK_RATE; qtime->timer_scale = IXP23XX_CLOCK_SCALE; qtime->cycles_per_sec = (uint64_t)IXP23XX_CLOCK_FREQ; add_callout_array(timer_callouts, sizeof(timer_callouts)); }
void init_qtime_ixp2400() { struct qtime_entry *qtime = alloc_qtime(); /* * Map the timer registers */ ixp2400_timer_base = startup_io_map(IXP2400_TIMER_SIZE, IXP2400_TIMER_BASE); /* * Set the timer free running with maximum countdown */ out32(ixp2400_timer_base + IXP2400_TIMER1_LOAD, 0xffffffff); out32(ixp2400_timer_base + IXP2400_TIMER1_CONTROL,0x80); timer_start = timer_start_ixp2400; timer_diff = timer_diff_ixp2400; qtime->intr = 4; qtime->timer_rate = IXP2400_CLOCK_RATE; qtime->timer_scale = IXP2400_CLOCK_SCALE; qtime->cycles_per_sec = (uint64_t)IXP2400_CLOCK_FREQ; add_callout_array(timer_callouts, sizeof(timer_callouts)); }
void init_qtime_pxa270() { struct qtime_entry *qtime = alloc_qtime(); /* * Map the timer registers */ pxa270_timer_base = startup_io_map(0x20, PXA250_TIMER_BASE); /* * Clear match status and interrupt enable, and disable watchdog reset */ out32(pxa270_timer_base + PXA250_OIER, in32(pxa270_timer_base + PXA250_OIER) & ~0xf);; out32(pxa270_timer_base + PXA250_OSSR, in32(pxa270_timer_base + PXA250_OSSR) | 0x0f); out32(pxa270_timer_base + PXA250_OWER, 0); timer_start = timer_start_pxa270; timer_diff = timer_diff_pxa270; qtime->intr = 26; qtime->timer_rate = PXA270_CLOCK_RATE; qtime->timer_scale = PXA270_CLOCK_SCALE; qtime->cycles_per_sec = (uint64_t)PXA270_CLOCK_FREQ; add_callout_array(timer_callouts, sizeof(timer_callouts)); }
void init_qtime_ixp425() { struct qtime_entry *qtime = alloc_qtime(); /* * Map the timer registers */ ixp425_timer_base = startup_io_map(IXP425_TIMER_SIZE, IXP425_TIMER_BASE); /* * Set the timer free running with maximum countdown */ out32(ixp425_timer_base + IXP425_TIMER0_RELOAD, 0xfffffffc); out32(ixp425_timer_base + IXP425_TIMER_STATUS, 0x5); timer_start = timer_start_ixp425; timer_diff = timer_diff_ixp425; qtime->intr = 5; //timer0 interrupt qtime->timer_rate = IXP425_CLOCK_RATE; qtime->timer_scale = IXP425_CLOCK_SCALE; qtime->cycles_per_sec = (uint64_t)IXP425_CLOCK_FREQ; add_callout_array(timer_callouts, sizeof(timer_callouts)); }
void init_qtime_omap3530() { struct qtime_entry *qtime = alloc_qtime(); uint32_t prcm_wkup_base = OMAP3530_PRCM_WKUP_CM; /* * Enable GPT1 clock, select sys_clk as timer input clock */ out32(prcm_wkup_base + OMAP3530_CM_FCLKEN_WKUP, in32(prcm_wkup_base + OMAP3530_CM_FCLKEN_WKUP) | 1); out32(prcm_wkup_base + OMAP3530_CM_ICLKEN_WKUP, in32(prcm_wkup_base + OMAP3530_CM_ICLKEN_WKUP) | 1); out32(prcm_wkup_base + OMAP3530_CM_CLKSEL_WKUP, in32(prcm_wkup_base + OMAP3530_CM_CLKSEL_WKUP) | 1); while ((in32(prcm_wkup_base + OMAP3530_CM_IDLEST_WKUP) & 1)); /* * Map GPT1 registers */ timer_base = startup_io_map(OMAP3530_GPT_SIZE, OMAP3530_GPT1_BASE); /* Reset the timer */ out32(timer_base + OMAP3530_GPT_TIOCP_CFG, 0x02); /* Wait for reset to complete */ while (!(in32(timer_base + OMAP3530_GPT_TISTAT)) & 1) ; /* Clear timer count and reload count */ out32(timer_base + OMAP3530_GPT_TLDR, 0); out32(timer_base + OMAP3530_GPT_TCRR, 0); /* * Setup GPT1 * Auto-reload enable * Prescaler disable * Stop timer, timer_load will enable it */ out32(timer_base + OMAP3530_GPT_TCLR, (1 << 1)); timer_start = timer_start_omap3530; timer_diff = timer_diff_omap3530; qtime->intr = 37; /* GPT1 irq */ #define OMAP_CLOCK_FREQ 13000000UL #define OMAP_CLOCK_RATE 76923077UL #define OMAP_CLOCK_SCALE -15 qtime->timer_rate = OMAP_CLOCK_RATE; qtime->timer_scale = OMAP_CLOCK_SCALE; qtime->cycles_per_sec = (uint64_t)OMAP_CLOCK_FREQ; add_callout_array(timer_callouts, sizeof(timer_callouts)); }
/* * init_qtime * * Initialize the qtime entry. The timer to use has been added to the HWINFO * section as "qtimer" */ void init_qtime() { struct qtime_entry *qtime = alloc_qtime(); // alloc_qtime() call rtc_time() unsigned hwi_off = hwi_find_device("qtimer", 0); hwiattr_timer_t qtimer_attr; int r = hwiattr_get_timer(hwi_off, &qtimer_attr); long best_freq; unsigned hires_timer; unsigned i; /* both asserts tells us which operation failed */ ASSERT(hwi_off != HWI_NULL_OFF); ASSERT(r == EOK); ASSERT(qtimer_attr.common.location.len > 0); ASSERT(qtimer_attr.common.location.base != NULL); ASSERT(qtimer_attr.num_clks > 0); qtime->intr = hwitag_find_ivec(hwi_off, NULL); ASSERT(qtime->intr != HWI_ILLEGAL_VECTOR); /* if multiple clock sources have been provided, choose the highest resolution */ best_freq = 0; hires_timer = 0; // we already know there is at least 1 clock source (see ASSERT above) for (i=0; i<qtimer_attr.num_clks; i++) { long freq = hwitag_find_clkfreq(hwi_off, &i); if ((i > 0) && (freq > best_freq)) { hires_timer = i; best_freq = freq; } } ASSERT(hires_timer <= 1); // I know CLKSEL is only 1 bit (ie. only 2 clock sources) qtime->timer_scale = -15; i = hires_timer; qtime->cycles_per_sec = (uint64_t)hwitag_find_clkfreq(hwi_off, &i); // don't pass hires_timer as its changed by the call ASSERT(qtime->cycles_per_sec > 0); qtime->timer_rate = QTIME_CLK_RATE(qtime->timer_scale, qtime->cycles_per_sec); // kprintf("cps = %x %x, rate = %d\n", ((uint32_t *)&qtime->cycles_per_sec)[0], ((uint32_t *)&qtime->cycles_per_sec)[1], qtime->timer_rate); /* Map the registers (timer_base) and select the hires_timer clock source and periodic mode */ timer_base = startup_io_map(qtimer_attr.common.location.len, qtimer_attr.common.location.base); ASSERT(timer_base != NULL); out32(timer_base + EP93xx_TIMER_LOAD, UINT32_MAX); // preset the LOAD register // kprintf("clksel(%d) = 0x%x\n", hires_timer, EP93xx_TIMER_CTRL_CLKSEL(hires_timer)); out32(timer_base + EP93xx_TIMER_CTRL, EP93xx_TIMER_CTRL_CLKSEL(hires_timer) | // hires_timer holds which clock to select EP93xx_TIMER_CTRL_CLKMODE_PERIODIC); timer_start = timer_start_ep93xx; timer_diff = timer_diff_ep93xx; add_callout_array(timer_callouts, sizeof(timer_callouts)); /* start the timer */ timer_start(); }
void init_qtime_ixp1200() { struct qtime_entry *qtime = alloc_qtime(); unsigned pll; static const char pll_mult[] = { /* * Multiplier for IXP1200_CLOCK_FREQ for PLL_CFG values * FIXME: these are taken from the Programmer's Reference Manual, * but I'm not sure they are actually 100% correct... */ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 36, 40, 42, 44, 45, 48, 52, 54, 56, 60, 63 }; /* * Map the timer registers */ ixp1200_timer_base = startup_io_map(IXP1200_TIMER_SIZE, IXP1200_TIMER_BASE); /* * Calulate CPU core PLL frequency */ pll = in32(IXP1200_PLL_CFG_BASE) & IXP1200_PLL_CFG_CCF; if (pll > 22) { crash("PLL_CFG is %d. Max supported value is 22\n", pll); } pll = IXP1200_CLOCK_FREQ * pll_mult[pll]; /* * Set the timer free running, divide by 16, with maximum countdown */ pll = pll / 16; out32(ixp1200_timer_base + IXP1200_TIMER_1_LOAD, 0x00ffffff); out32(ixp1200_timer_base + IXP1200_TIMER_1_CONTROL, IXP1200_TIMER_CONTROL_EN | IXP1200_TIMER_CONTROL_STP_16 | IXP1200_TIMER_CONTROL_FREE); timer_start = timer_start_ixp1200; timer_diff = timer_diff_ixp1200; qtime->intr = 36; qtime->timer_rate = IXP1200_CLOCK_RATE; qtime->timer_scale = IXP1200_CLOCK_SCALE; qtime->cycles_per_sec = (uint64_t)pll; invert_timer_freq(qtime, pll); add_callout_array(timer_callouts, sizeof(timer_callouts)); }