예제 #1
0
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));
}
예제 #2
0
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));
}
예제 #3
0
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));
}
예제 #4
0
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));
}
예제 #5
0
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();
}
예제 #7
0
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));
}