예제 #1
0
/*
 * void __init iSeries_calibrate_decr()
 *
 * Description:
 *   This routine retrieves the internal processor frequency from the VPD,
 *   and sets up the kernel timer decrementer based on that value.
 *
 */
void __init iSeries_calibrate_decr(void)
{
	unsigned long	cyclesPerUsec;
	struct div_result divres;
	
	/* Compute decrementer (and TB) frequency in cycles/sec */
	cyclesPerUsec = ppc_tb_freq / 1000000;

	/*
	 * Set the amount to refresh the decrementer by.  This
	 * is the number of decrementer ticks it takes for 
	 * 1/HZ seconds.
	 */
	tb_ticks_per_jiffy = ppc_tb_freq / HZ;

#if 0
	/* TEST CODE FOR ADJTIME */
	tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
	/* END OF TEST CODE */
#endif

	/*
	 * tb_ticks_per_sec = freq; would give better accuracy
	 * but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
	 * that jiffies (and xtime) will match the time returned
	 * by do_gettimeofday.
	 */
	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
	tb_ticks_per_usec = cyclesPerUsec;
	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
	div128_by_32(1024 * 1024, 0, tb_ticks_per_sec, &divres);
	tb_to_xs = divres.result_low;
	setup_default_decr();
}
예제 #2
0
/*
 * This routine retrieves the internal processor frequency from the board
 * information structure, sets up the kernel timer decrementer based on
 * that value, enables the 4xx programmable interval timer (PIT) and sets
 * it up for auto-reload.
 */
static void __init
ppc4xx_calibrate_decr(void)
{
	unsigned int freq;
	bd_t *bip = &__res;

#if defined(CONFIG_WALNUT) || defined(CONFIG_SYCAMORE)
	/* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */
	mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE);
#endif
	freq = bip->bi_tbfreq;
	tb_ticks_per_jiffy = freq / HZ;
	tb_to_us = mulhwu_scale_factor(freq, 1000000);

	/* Set the time base to zero.
	   ** At 200 Mhz, time base will rollover in ~2925 years.
	 */

	mtspr(SPRN_TBWL, 0);
	mtspr(SPRN_TBWU, 0);

	/* Clear any pending timer interrupts */

	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);

	/* Set the PIT reload value and just let it run. */
	mtspr(SPRN_PIT, tb_ticks_per_jiffy);
}
예제 #3
0
/*
 * This was taken from prep_setup.c
 * Use the NVRAM RTC to time a second to calibrate the decrementer.
 */
void __init
todc_calibrate_decr(void)
{
	ulong	freq;
	ulong	tbl, tbu;
        long	i, loop_count;
        u_char	sec;

	todc_time_init();

	/*
	 * Actually this is bad for precision, we should have a loop in
	 * which we only read the seconds counter. todc_read_val writes
	 * the address bytes on every call and this takes a lot of time.
	 * Perhaps an nvram_wait_change method returning a time
	 * stamp with a loop count as parameter would be the solution.
	 */
	/*
	 * Need to make sure the tbl doesn't roll over so if tbu increments
	 * during this test, we need to do it again.
	 */
	loop_count = 0;

	sec = todc_read_timereg(todc_info->seconds) & 0x7f;

	do {
		tbu = get_tbu();

		for (i = 0 ; i < 10000000 ; i++) {/* may take up to 1 second */
		   tbl = get_tbl();

		   if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) {
		      break;
		   }
		}

		sec = todc_read_timereg(todc_info->seconds) & 0x7f;

		for (i = 0 ; i < 10000000 ; i++) { /* Should take 1 second */
		   freq = get_tbl();

		   if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) {
		      break;
		   }
		}

		freq -= tbl;
	} while ((get_tbu() != tbu) && (++loop_count < 2));

	printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
	       freq/1000000, freq%1000000);

	tb_ticks_per_jiffy = freq / HZ;
	tb_to_us = mulhwu_scale_factor(freq, 1000000);

	return;
}
예제 #4
0
static void __init prpmc750_calibrate_decr(void)
{
	unsigned long freq;
	int divisor = 4;

	freq = prpmc750_get_bus_speed();

	tb_ticks_per_jiffy = freq / (HZ * divisor);
	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
}
예제 #5
0
/* The decrementer counts at the system (internal) clock frequency
 * divided by four.
 */
static void __init
m8260_calibrate_decr(void)
{
	bd_t *binfo = (bd_t *)__res;
	int freq, divisor;

	freq = binfo->bi_busfreq;
        divisor = 4;
        tb_ticks_per_jiffy = freq / HZ / divisor;
	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
}
예제 #6
0
파일: glacier.c 프로젝트: leonsh/eldk30ppc
static void __init
glacier_calibrate_decr(void)
{
	int freq, divisor;

	freq = 231000000/3.5;
	printk("hardcoded clock to 231MHz, need to calculate it\n");
	divisor = 4;
	tb_ticks_per_jiffy = freq / HZ / divisor;
	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
}
예제 #7
0
static void __init ppc7d_calibrate_decr(void)
{
	ulong freq;

	freq = 100000000 / 4;

	pr_debug("time_init: decrementer frequency = %lu.%.6lu MHz\n",
		 freq / 1000000, freq % 1000000);

	tb_ticks_per_jiffy = freq / HZ;
	tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
예제 #8
0
/* The decrementer counts at the system (internal) clock freq divided by 4 */
void __init
mpc83xx_calibrate_decr(void)
{
        bd_t *binfo = (bd_t *) __res;
        unsigned int freq, divisor;

	freq = binfo->bi_busfreq;
	divisor = 4;
	tb_ticks_per_jiffy = freq / HZ / divisor;
	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
	us_to_tb = (freq / divisor) / 1000000;
}
예제 #9
0
static void __init
powerpmc250_calibrate_decr(void)
{
	unsigned long freq;
	int divisor = 4;

	//freq = powerpmc250_get_bus_speed();
#warning hardcoded bus freq
	freq = 100000000;

	tb_ticks_per_jiffy = freq / (HZ * divisor);
	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
}
예제 #10
0
/**************************************************************************
 * FUNCTION: chestnut_calibrate_decr
 *
 * DESCRIPTION: initialize decrementer interrupt frequency (used as system
 *              timer)
 *
 ****/
static void __init
chestnut_calibrate_decr(void)
{
    ulong freq;

    freq = CHESTNUT_BUS_SPEED / 4;

    printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
           freq/1000000, freq%1000000);

    tb_ticks_per_jiffy = freq / HZ;
    tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
예제 #11
0
void __init ibm44x_calibrate_decr(unsigned int freq)
{
	tb_ticks_per_jiffy = freq / HZ;
	tb_to_us = mulhwu_scale_factor(freq, 1000000);

	/* Set the time base to zero */
	mtspr(SPRN_TBWL, 0);
	mtspr(SPRN_TBWU, 0);

	/* Clear any pending timer interrupts */
	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);

	/* Enable decrementer interrupt */
	mtspr(SPRN_TCR, TCR_DIE);
}
예제 #12
0
/* The decrementer counts at the system (internal) clock freq divided by 8 */
void __init
mpc86xx_calibrate_decr(void)
{
	bd_t *binfo = (bd_t *) __res;
	unsigned int freq, divisor, temp;

	/* get the core frequency */
	freq = binfo->bi_busfreq;

	/* The timebase is updated every 4 bus clocks */
	divisor = 4;
	tb_ticks_per_jiffy = freq / divisor / HZ;
	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);

	/* Set the time base to zero */
	mtspr(SPRN_TBWL, 0);
	mtspr(SPRN_TBWU, 0);

	temp = mfspr(SPRN_HID0);
	temp |= HID0_TBEN;
	mtspr(SPRN_HID0, temp);
}
예제 #13
0
/* The decrementer counts at the system (internal) clock freq divided by 8 */
void __init
mpc85xx_calibrate_decr(void)
{
        bd_t *binfo = (bd_t *) __res;
        unsigned int freq, divisor;

        /* get the core frequency */
        freq = binfo->bi_busfreq;

        /* The timebase is updated every 8 bus clocks, HID0[SEL_TBCLK] = 0 */
        divisor = 8;
        tb_ticks_per_jiffy = freq / divisor / HZ;
        tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);

	/* Set the time base to zero */
	mtspr(SPRN_TBWL, 0);
	mtspr(SPRN_TBWU, 0);

	/* Clear any pending timer interrupts */
	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);

	/* Enable decrementer interrupt */
	mtspr(SPRN_TCR, TCR_DIE);
}
예제 #14
0
void __init
mpc52xx_calibrate_decr(void)
{
    int current_time, previous_time;
    int tbl_start, tbl_end;
    unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;

    xlbfreq = __res.bi_busfreq;
    /* if bootloader didn't pass bus frequencies, calculate them */
    if (xlbfreq == 0) {
        /* Get RTC & Clock manager modules */
        struct mpc52xx_rtc __iomem *rtc;
        struct mpc52xx_cdm __iomem *cdm;

        rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
        cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);

        if ((rtc==NULL) || (cdm==NULL))
            panic("Can't ioremap RTC/CDM while computing bus freq");

        /* Count bus clock during 1/64 sec */
        out_be32(&rtc->dividers, 0x8f1f0000);	/* Set RTC 64x faster */
        previous_time = in_be32(&rtc->time);
        while ((current_time = in_be32(&rtc->time)) == previous_time) ;
        tbl_start = get_tbl();
        previous_time = current_time;
        while ((current_time = in_be32(&rtc->time)) == previous_time) ;
        tbl_end = get_tbl();
        out_be32(&rtc->dividers, 0xffff0000);	/* Restore RTC */

        /* Compute all frequency from that & CDM settings */
        xlbfreq = (tbl_end - tbl_start) << 8;
        cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
        ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
                  xlbfreq / 2 : xlbfreq;
        switch (in_8(&cdm->pci_clk_sel) & 3) {
        case 0:
            pcifreq = ipbfreq;
            break;
        case 1:
            pcifreq = ipbfreq / 2;
            break;
        default:
            pcifreq = xlbfreq / 4;
            break;
        }
        __res.bi_busfreq = xlbfreq;
        __res.bi_intfreq = cpufreq;
        __res.bi_ipbfreq = ipbfreq;
        __res.bi_pcifreq = pcifreq;

        /* Release mapping */
        iounmap(rtc);
        iounmap(cdm);
    }

    divisor = 4;

    tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
    tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}