From: Tom Rini - Convert PPC_PREP to using the todc_time.c functions instead of its own copy of them. --- /dev/null | 225 -------------------------------- 25-akpm/arch/ppc/platforms/Makefile | 2 25-akpm/arch/ppc/platforms/prep_setup.c | 177 ++----------------------- 25-akpm/arch/ppc/syslib/Makefile | 2 4 files changed, 20 insertions(+), 386 deletions(-) diff -puN arch/ppc/platforms/Makefile~ppc32-prep-use-todc_time arch/ppc/platforms/Makefile --- 25/arch/ppc/platforms/Makefile~ppc32-prep-use-todc_time Tue Feb 10 12:54:24 2004 +++ 25-akpm/arch/ppc/platforms/Makefile Tue Feb 10 12:54:24 2004 @@ -20,7 +20,7 @@ obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pm pmac_feature.o pmac_pci.o pmac_sleep.o \ pmac_low_i2c.o obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o -obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_time.o prep_setup.o +obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o ifeq ($(CONFIG_PPC_PMAC),y) obj-$(CONFIG_NVRAM) += pmac_nvram.o obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o diff -puN arch/ppc/platforms/prep_setup.c~ppc32-prep-use-todc_time arch/ppc/platforms/prep_setup.c --- 25/arch/ppc/platforms/prep_setup.c~ppc32-prep-use-todc_time Tue Feb 10 12:54:24 2004 +++ 25-akpm/arch/ppc/platforms/prep_setup.c Tue Feb 10 12:54:24 2004 @@ -58,16 +58,14 @@ #include #include #include +#include + +TODC_ALLOC(); unsigned char ucSystemType; unsigned char ucBoardRev; unsigned char ucBoardRevMaj, ucBoardRevMin; -extern unsigned long mc146818_get_rtc_time(void); -extern int mc146818_set_rtc_time(unsigned long nowtime); -extern unsigned long mk48t59_get_rtc_time(void); -extern int mk48t59_set_rtc_time(unsigned long nowtime); - extern unsigned char prep_nvram_read_val(int addr); extern void prep_nvram_write_val(int addr, unsigned char val); @@ -814,12 +812,12 @@ prep_setup_arch(void) } /* - * Determine the decrementer frequency from the residual data - * This allows for a faster boot as we do not need to calibrate the - * decrementer against another clock. This is important for embedded systems. + * First, see if we can get this information from the residual data. + * This is important on some IBM PReP systems. If we cannot, we let the + * TODC code handle doing this. */ -static int __init -prep_res_calibrate_decr(void) +static void __init +prep_calibrate_decr(void) { #ifdef CONFIG_PREP_RESIDUAL unsigned long freq, divisor = 4; @@ -831,149 +829,9 @@ prep_res_calibrate_decr(void) (freq/divisor)%1000000); tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); tb_ticks_per_jiffy = freq / HZ / divisor; - return 0; } else #endif - return 1; -} - -/* - * Uses the on-board timer to calibrate the on-chip decrementer register - * for prep systems. On the pmac the OF tells us what the frequency is - * but on prep we have to figure it out. - * -- Cort - */ -/* Done with 3 interrupts: the first one primes the cache and the - * 2 following ones measure the interval. The precision of the method - * is still doubtful due to the short interval sampled. - */ -static volatile int calibrate_steps __initdata = 3; -static unsigned tbstamp __initdata = 0; - -static irqreturn_t __init -prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs) -{ - unsigned long t, freq; - int step=--calibrate_steps; - - t = get_tbl(); - if (step > 0) { - tbstamp = t; - } else { - freq = (t - tbstamp)*HZ; - 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 IRQ_HANDLED; -} - -static void __init -prep_calibrate_decr(void) -{ - int res; - - /* Try and get this from the residual data. */ - res = prep_res_calibrate_decr(); - - /* If we didn't get it from the residual data, try this. */ - if ( res ) { -#define TIMER0_COUNT 0x40 -#define TIMER_CONTROL 0x43 - /* set timer to periodic mode */ - outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */ - /* set the clock to ~100 Hz */ - outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ - outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ - - if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0) - panic("Could not allocate timer IRQ!"); - local_irq_enable(); - /* wait for calibrate */ - while ( calibrate_steps ) - ; - local_irq_disable(); - free_irq( 0, NULL); - } -} - -static long __init -mk48t59_init(void) { - unsigned char tmp; - - tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); - if (tmp & MK48T59_RTC_CB_STOP) { - printk("Warning: RTC was stopped, date will be wrong.\n"); - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, - tmp & ~MK48T59_RTC_CB_STOP); - /* Low frequency crystal oscillators may take a very long - * time to startup and stabilize. For now just ignore the - * the issue, but attempting to calibrate the decrementer - * from the RTC just after this wakeup is likely to be very - * inaccurate. Firmware should not allow to load - * the OS with the clock stopped anyway... - */ - } - /* Ensure that the clock registers are updated */ - tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE); - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp); - return 0; -} - -/* We use the NVRAM RTC to time a second to calibrate the decrementer, - * the RTC registers have just been set up in the right state by the - * preceding routine. - */ -static void __init -mk48t59_calibrate_decr(void) -{ - unsigned long freq; - unsigned long t1; - unsigned char save_control; - long i; - unsigned char sec; - - - /* Make sure the time is not stopped. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); - - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control & (~MK48T59_RTC_CB_STOP))); - - /* Now make sure the read bit is off so the value will change. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - save_control &= ~MK48T59_RTC_CA_READ; - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - - /* Read the seconds value to see when it changes. */ - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - /* Actually this is bad for precision, we should have a loop in - * which we only read the seconds counter. nvram_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. - */ - for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */ - t1 = get_tbl(); - if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { - break; - } - } - - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */ - freq = get_tbl()-t1; - if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) - break; - } - - 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); + todc_calibrate_decr(); } static unsigned int __prep @@ -1163,18 +1021,19 @@ prep_init(unsigned long r3, unsigned lon ppc_md.nvram_read_val = prep_nvram_read_val; ppc_md.nvram_write_val = prep_nvram_write_val; - ppc_md.time_init = NULL; + ppc_md.time_init = todc_time_init; if (_prep_type == _PREP_IBM) { - ppc_md.set_rtc_time = mc146818_set_rtc_time; - ppc_md.get_rtc_time = mc146818_get_rtc_time; - ppc_md.calibrate_decr = prep_calibrate_decr; + TODC_INIT(TODC_TYPE_MC146818, PREP_NVRAM_AS0, PREP_NVRAM_AS1, + PREP_NVRAM_DATA, 8); } else { - ppc_md.set_rtc_time = mk48t59_set_rtc_time; - ppc_md.get_rtc_time = mk48t59_get_rtc_time; - ppc_md.calibrate_decr = mk48t59_calibrate_decr; - ppc_md.time_init = mk48t59_init; + TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1, + PREP_NVRAM_DATA, 8); } + ppc_md.calibrate_decr = prep_calibrate_decr; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.setup_io_mappings = prep_map_io; #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) diff -puN -L arch/ppc/platforms/prep_time.c arch/ppc/platforms/prep_time.c~ppc32-prep-use-todc_time /dev/null --- 25/arch/ppc/platforms/prep_time.c +++ /dev/null Thu Apr 11 07:25:15 2002 @@ -1,225 +0,0 @@ -/* - * arch/ppc/platforms/prep_time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * - * Adapted for PowerPC (PReP) by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu). - * Copied and modified from arch/i386/kernel/time.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -extern spinlock_t rtc_lock; - -/* - * The motorola uses the m48t18 rtc (includes DS1643) whose registers - * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818 - * rtc (ds1386) which has regs at addr 0-d). The intel gets - * past this because the bios emulates the mc146818. - * - * Why in the world did they have to use different clocks? - * - * Right now things are hacked to check which machine we're on then - * use the appropriate macro. This is very very ugly and I should - * probably have a function that checks which machine we're on then - * does things correctly transparently or a function pointer which - * is setup at boot time to use the correct addresses. - * -- Cort - */ - -/* - * Set the hardware clock. -- Cort - */ -__prep -int mc146818_set_rtc_time(unsigned long nowtime) -{ - unsigned char save_control, save_freq_select; - struct rtc_time tm; - - spin_lock(&rtc_lock); - to_tm(nowtime, &tm); - - /* tell the clock it's being set */ - save_control = CMOS_READ(RTC_CONTROL); - - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - /* stop and reset prescaler */ - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); - - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - tm.tm_year = (tm.tm_year - 1900) % 100; - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - } - CMOS_WRITE(tm.tm_sec, RTC_SECONDS); - CMOS_WRITE(tm.tm_min, RTC_MINUTES); - CMOS_WRITE(tm.tm_hour, RTC_HOURS); - CMOS_WRITE(tm.tm_mon, RTC_MONTH); - CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH); - CMOS_WRITE(tm.tm_year, RTC_YEAR); - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock(&rtc_lock); - - return 0; -} - -__prep -unsigned long mc146818_get_rtc_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - int uip, i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - - /* Since the UIP flag is set for about 2.2 ms and the clock - * is typically written with a precision of 1 jiffy, trying - * to obtain a precision better than a few milliseconds is - * an illusion. Only consistency is interesting, this also - * allows to use the routine for /dev/rtc without a potential - * 1 second kernel busy loop triggered by any reader of /dev/rtc. - */ - - for ( i = 0; i<1000000; i++) { - uip = CMOS_READ(RTC_FREQ_SELECT); - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - uip |= CMOS_READ(RTC_FREQ_SELECT); - if ((uip & RTC_UIP)==0) break; - } - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) - || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; - return mktime(year, mon, day, hour, min, sec); -} - -__prep -int mk48t59_set_rtc_time(unsigned long nowtime) -{ - unsigned char save_control; - struct rtc_time tm; - - spin_lock(&rtc_lock); - to_tm(nowtime, &tm); - - /* tell the clock it's being written */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control | MK48T59_RTC_CA_WRITE)); - - tm.tm_year = (tm.tm_year - 1900) % 100; - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - - ppc_md.nvram_write_val(MK48T59_RTC_SECONDS, tm.tm_sec); - ppc_md.nvram_write_val(MK48T59_RTC_MINUTES, tm.tm_min); - ppc_md.nvram_write_val(MK48T59_RTC_HOURS, tm.tm_hour); - ppc_md.nvram_write_val(MK48T59_RTC_MONTH, tm.tm_mon); - ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday); - ppc_md.nvram_write_val(MK48T59_RTC_YEAR, tm.tm_year); - - /* Turn off the write bit. */ - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - spin_unlock(&rtc_lock); - - return 0; -} - -__prep -unsigned long mk48t59_get_rtc_time(void) -{ - unsigned char save_control; - unsigned int year, mon, day, hour, min, sec; - - /* Simple: freeze the clock, read it and allow updates again */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - save_control &= ~MK48T59_RTC_CA_READ; - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - /* Set the register to read the value. */ - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control | MK48T59_RTC_CA_READ)); - - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES); - hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS); - day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH); - mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH); - year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR); - - /* Let the time values change again. */ - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - - year = year + 1900; - if (year < 1970) { - year += 100; - } - - return mktime(year, mon, day, hour, min, sec); -} diff -puN arch/ppc/syslib/Makefile~ppc32-prep-use-todc_time arch/ppc/syslib/Makefile --- 25/arch/ppc/syslib/Makefile~ppc32-prep-use-todc_time Tue Feb 10 12:54:24 2004 +++ 25-akpm/arch/ppc/syslib/Makefile Tue Feb 10 12:54:24 2004 @@ -33,7 +33,7 @@ obj-$(CONFIG_PPC_OF) += prom_init.o pro obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o obj-$(CONFIG_POWER4) += open_pic2.o obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o -obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o +obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \ todc_time.o obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o _