From: Tom Rini <trini@kernel.crashing.org>

- 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 <asm/i8259.h>
 #include <asm/open_pic.h>
 #include <asm/pci-bridge.h>
+#include <asm/todc.h>
+
+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 <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-#include <linux/bcd.h>
-
-#include <asm/sections.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prep_nvram.h>
-#include <asm/mk48t59.h>
-
-#include <asm/time.h>
-
-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

_