[MIPS] Deforest the function pointer jungle in the time code.

Hard to follow who is pointing what to where and why so it's simply getting
in the way of the time code renovation.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index a95b377..b212c07 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -50,7 +50,6 @@
 extern void au1000_power_off(void);
 extern void au1x_time_init(void);
 extern void au1x_timer_setup(struct irqaction *irq);
-extern void au1xxx_time_init(void);
 extern void set_cpuspec(void);
 
 void __init plat_mem_setup(void)
@@ -112,7 +111,6 @@
 	_machine_restart = au1000_restart;
 	_machine_halt = au1000_halt;
 	pm_power_off = au1000_power_off;
-	board_time_init = au1xxx_time_init;
 
 	/* IO/MEM resources. */
 	set_io_port_base(0);
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index 8fc2998..fb1fd50 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -329,7 +329,3 @@
 
 #endif
 }
-
-void __init au1xxx_time_init(void)
-{
-}
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
index 5600318..68be19d 100644
--- a/arch/mips/basler/excite/excite_setup.c
+++ b/arch/mips/basler/excite/excite_setup.c
@@ -68,7 +68,7 @@
 int titan_irqflags;
 
 
-static void excite_timer_init(void)
+void __init plat_time_init(void)
 {
 	const u32 modebit5 = ocd_readl(0x00e4);
 	unsigned int
@@ -261,9 +261,6 @@
 	/* Announce RAM to system */
 	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
 
-	/* Set up timer initialization hooks */
-	board_time_init = excite_timer_init;
-
 	/* Set up the peripheral address map */
 	*(boot_ocd_base + (LKB9 / sizeof (u32))) = 0;
 	*(boot_ocd_base + (LKB10 / sizeof (u32))) = 0;
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index f48aa5a..1b6b0fa 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -119,6 +119,5 @@
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
 	pm_power_off = bcm47xx_machine_halt;
-	board_time_init = bcm47xx_time_init;
 }
 
diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
index b27d07f..0ab4676 100644
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -28,8 +28,7 @@
 #include <asm/time.h>
 #include <bcm47xx.h>
 
-void __init
-bcm47xx_time_init(void)
+void __init plat_time_init(void)
 {
 	unsigned long hz;
 
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 3e634f2f..bd5431e 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -145,13 +145,9 @@
 	}
 }
 
-
-extern void dec_time_init(void);
-
 void __init plat_mem_setup(void)
 {
 	board_be_init = dec_be_init;
-	board_time_init = dec_time_init;
 
 	wbflush_setup();
 
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index e2973a43..820e533 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -35,7 +35,7 @@
 #include <asm/dec/ioasic_addrs.h>
 #include <asm/dec/machtype.h>
 
-static unsigned long dec_rtc_get_time(void)
+unsigned long read_persistent_clock(void)
 {
 	unsigned int year, mon, day, hour, min, sec, real_year;
 	unsigned long flags;
@@ -74,13 +74,13 @@
 }
 
 /*
- * In order to set the CMOS clock precisely, dec_rtc_set_mmss has to
+ * In order to set the CMOS clock precisely, rtc_mips_set_mmss has to
  * be called 500 ms after the second nowtime has started, because when
  * nowtime is written into the registers of the CMOS clock, it will
  * jump to the next second precisely 500 ms later.  Check the Dallas
  * DS1287 data sheet for details.
  */
-static int dec_rtc_set_mmss(unsigned long nowtime)
+int rtc_mips_set_mmss(unsigned long nowtime)
 {
 	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
@@ -139,7 +139,6 @@
 	return retval;
 }
 
-
 static int dec_timer_state(void)
 {
 	return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
@@ -160,11 +159,8 @@
 }
 
 
-void __init dec_time_init(void)
+void __init plat_time_init(void)
 {
-	rtc_mips_get_time = dec_rtc_get_time;
-	rtc_mips_set_mmss = dec_rtc_set_mmss;
-
 	mips_timer_state = dec_timer_state;
 	mips_timer_ack = dec_timer_ack;
 
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
index 2f060e1..5e1da53 100644
--- a/arch/mips/emma2rh/markeins/setup.c
+++ b/arch/mips/emma2rh/markeins/setup.c
@@ -88,7 +88,7 @@
 	return clock[reg];
 }
 
-static void __init emma2rh_time_init(void)
+void __init plat_time_init(void)
 {
 	u32 reg;
 	if (bus_frequency == 0)
@@ -124,8 +124,6 @@
 
 	set_io_port_base(KSEG1ADDR(EMMA2RH_PCI_IO_BASE));
 
-	board_time_init = emma2rh_time_init;
-
 	_machine_restart = markeins_machine_restart;
 	_machine_halt = markeins_machine_halt;
 	pm_power_off = markeins_machine_power_off;
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
index 238b508..f2ccf10 100644
--- a/arch/mips/gt64120/wrppmc/setup.c
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -126,7 +126,6 @@
 
 void __init plat_mem_setup(void)
 {
-	extern void wrppmc_time_init(void);
 	extern void wrppmc_machine_restart(char *command);
 	extern void wrppmc_machine_halt(void);
 	extern void wrppmc_machine_power_off(void);
@@ -135,9 +134,6 @@
 	_machine_halt	 = wrppmc_machine_halt;
 	pm_power_off	 = wrppmc_machine_power_off;
 
-	/* Use MIPS Count/Compare Timer */
-	board_time_init   = wrppmc_time_init;
-
 	/* This makes the operations of 'in/out[bwl]' to the
 	 * physical address ( < KSEG0) can work via KSEG1
 	 */
diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c
index 5b44085..faf164e 100644
--- a/arch/mips/gt64120/wrppmc/time.c
+++ b/arch/mips/gt64120/wrppmc/time.c
@@ -38,7 +38,7 @@
  * NOTE: We disable all GT64120 timers, and use MIPS processor internal
  * timer as the source of kernel clock tick.
  */
-void __init wrppmc_time_init(void)
+void __init plat_time_init(void)
 {
 	/* Disable GT64120 timers */
 	GT_WRITE(GT_TC_CONTROL_OFS, 0x00);
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index fde56e8..7f14f70 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -109,7 +109,7 @@
 	jmr3927_tmrptr->tisr = 0;       /* ack interrupt */
 }
 
-static void __init jmr3927_time_init(void)
+void __init plat_time_init(void)
 {
 	clocksource_mips.read = jmr3927_hpt_read;
 	mips_timer_ack = jmr3927_timer_ack;
@@ -141,8 +141,6 @@
 
 	set_io_port_base(JMR3927_PORT_BASE + JMR3927_PCIIO);
 
-	board_time_init = jmr3927_time_init;
-
 	_machine_restart = jmr3927_machine_restart;
 	_machine_halt = jmr3927_machine_halt;
 	pm_power_off = jmr3927_machine_power_off;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 628a8ba..9bbbd9b 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -49,23 +49,18 @@
  * forward reference
  */
 DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
 
-/*
- * By default we provide the null RTC ops
- */
-static unsigned long null_rtc_get_time(void)
-{
-	return mktime(2000, 1, 1, 0, 0, 0);
-}
-
-static int null_rtc_set_time(unsigned long sec)
+int __weak rtc_mips_set_time(unsigned long sec)
 {
 	return 0;
 }
+EXPORT_SYMBOL(rtc_mips_set_time);
 
-unsigned long (*rtc_mips_get_time)(void) = null_rtc_get_time;
-int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time;
-int (*rtc_mips_set_mmss)(unsigned long);
+int __weak rtc_mips_set_mmss(unsigned long nowtime)
+{
+	return rtc_mips_set_time(nowtime);
+}
 
 int update_persistent_clock(struct timespec now)
 {
@@ -247,21 +242,18 @@
 /*
  * time_init() - it does the following things.
  *
- * 1) board_time_init() -
+ * 1) plat_time_init() -
  * 	a) (optional) set up RTC routines,
  *      b) (optional) calibrate and set the mips_hpt_frequency
  *	    (only needed if you intended to use cpu counter as timer interrupt
  *	     source)
- * 2) setup xtime based on rtc_mips_get_time().
- * 3) calculate a couple of cached variables for later usage
- * 4) plat_timer_setup() -
+ * 2) calculate a couple of cached variables for later usage
+ * 3) plat_timer_setup() -
  *	a) (optional) over-write any choices made above by time_init().
  *	b) machine specific code should setup the timer irqaction.
  *	c) enable the timer interrupt
  */
 
-void (*board_time_init)(void);
-
 unsigned int mips_hpt_frequency;
 
 static struct irqaction timer_irqaction = {
@@ -341,19 +333,13 @@
 	clocksource_register(&clocksource_mips);
 }
 
+void __init __weak plat_time_init(void)
+{
+}
+
 void __init time_init(void)
 {
-	if (board_time_init)
-		board_time_init();
-
-	if (!rtc_mips_set_mmss)
-		rtc_mips_set_mmss = rtc_mips_set_time;
-
-	xtime.tv_sec = rtc_mips_get_time();
-	xtime.tv_nsec = 0;
-
-	set_normalized_timespec(&wall_to_monotonic,
-	                        -xtime.tv_sec, -xtime.tv_nsec);
+	plat_time_init();
 
 	/* Choose appropriate high precision timer routines.  */
 	if (!cpu_has_counter && !clocksource_mips.read)
@@ -459,7 +445,4 @@
 	tm->tm_wday = (gday + 4) % 7;	/* 1970/1/1 was Thursday */
 }
 
-EXPORT_SYMBOL(rtc_lock);
 EXPORT_SYMBOL(to_tm);
-EXPORT_SYMBOL(rtc_mips_set_time);
-EXPORT_SYMBOL(rtc_mips_get_time);
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
index 0b315f5..52cb143 100644
--- a/arch/mips/lasat/ds1603.c
+++ b/arch/mips/lasat/ds1603.c
@@ -135,8 +135,7 @@
 	lasat_ndelay(1000);
 }
 
-/* interface */
-unsigned long ds1603_read(void)
+unsigned long read_persistent_clock(void)
 {
 	unsigned long word;
 	unsigned long flags;
@@ -147,10 +146,11 @@
 	word = rtc_read_word();
 	rtc_end_op();
 	spin_unlock_irqrestore(&rtc_lock, flags);
+
 	return word;
 }
 
-int ds1603_set(unsigned long time)
+int rtc_mips_set_mmss(unsigned long time)
 {
 	unsigned long flags;
 
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
index c2e5c76..2da3704 100644
--- a/arch/mips/lasat/ds1603.h
+++ b/arch/mips/lasat/ds1603.h
@@ -20,8 +20,6 @@
 
 extern struct ds_defs *ds1603;
 
-unsigned long ds1603_read(void);
-int ds1603_set(unsigned long);
 void ds1603_set_trimmer(unsigned int);
 void ds1603_enable(void);
 void ds1603_disable(void);
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index 187e378..54827d0 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -117,7 +117,7 @@
 	}
 };
 
-static void lasat_time_init(void)
+void plat_time_init(void)
 {
 	mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
 }
@@ -142,12 +142,8 @@
 
 	lasat_reboot_setup();
 
-	board_time_init = lasat_time_init;
-
 #ifdef CONFIG_DS1603
 	ds1603 = &ds_defs[mips_machtype];
-	rtc_mips_get_time = ds1603_read;
-	rtc_mips_set_time = ds1603_set;
 #endif
 
 #ifdef DYNAMIC_SERIAL_INIT
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 4575a82..389336c 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -32,6 +32,8 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 
+#include <asm/time.h>
+
 #include "sysctl.h"
 #include "ds1603.h"
 
@@ -106,7 +108,7 @@
 
 	mutex_lock(&lasat_info_mutex);
 	if (!write) {
-		rtctmp = ds1603_read();
+		rtctmp = read_persistent_clock();
 		/* check for time < 0 and set to 0 */
 		if (rtctmp < 0)
 			rtctmp = 0;
@@ -116,7 +118,7 @@
 		mutex_unlock(&lasat_info_mutex);
 		return r;
 	}
-	ds1603_set(rtctmp);
+	rtc_mips_set_mmss(rtctmp);
 	mutex_unlock(&lasat_info_mutex);
 
 	return 0;
@@ -152,7 +154,7 @@
 	int r;
 
 	mutex_lock(&lasat_info_mutex);
-	rtctmp = ds1603_read();
+	rtctmp = read_persistent_clock();
 	if (rtctmp < 0)
 		rtctmp = 0;
 	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
@@ -161,7 +163,7 @@
 		return r;
 	}
 	if (newval && newlen)
-		ds1603_set(rtctmp);
+		rtc_mips_set_mmss(rtctmp);
 	mutex_unlock(&lasat_info_mutex);
 
 	return 1;
diff --git a/arch/mips/lemote/lm2e/setup.c b/arch/mips/lemote/lm2e/setup.c
index f34350a..09314a2 100644
--- a/arch/mips/lemote/lm2e/setup.c
+++ b/arch/mips/lemote/lm2e/setup.c
@@ -58,13 +58,13 @@
 	setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
 }
 
-static void __init loongson2e_time_init(void)
+void __init plat_time_init(void)
 {
 	/* setup mips r4k timer */
 	mips_hpt_frequency = cpu_clock_freq / 2;
 }
 
-static unsigned long __init mips_rtc_get_time(void)
+unsigned long read_persistent_clock(void)
 {
 	return mc146818_get_cmos_time();
 }
@@ -89,9 +89,6 @@
 
 	mips_reboot_setup();
 
-	board_time_init = loongson2e_time_init;
-	rtc_mips_get_time = mips_rtc_get_time;
-
 	__wbflush = wbflush_loongson2e;
 
 	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index c68358a..86bfc05 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -35,8 +35,6 @@
 #include <asm/traps.h>
 
 extern void mips_reboot_setup(void);
-extern void mips_time_init(void);
-extern unsigned long mips_rtc_get_time(void);
 
 #ifdef CONFIG_KGDB
 extern void kgdb_config(void);
@@ -63,9 +61,6 @@
 	kgdb_config();
 #endif
 	mips_reboot_setup();
-
-	board_time_init = mips_time_init;
-	rtc_mips_get_time = mips_rtc_get_time;
 }
 
 static void __init serial_init(void)
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index d7bff9c..075f9d4 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -224,12 +224,12 @@
 	return count;
 }
 
-unsigned long __init mips_rtc_get_time(void)
+unsigned long read_persistent_clock(void)
 {
 	return mc146818_get_cmos_time();
 }
 
-void __init mips_time_init(void)
+void __init plat_time_init(void)
 {
 	unsigned int est_freq;
 
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 8f1b78d..a5a5a43 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -36,7 +36,6 @@
 #endif
 
 extern void mips_reboot_setup(void);
-extern void mips_time_init(void);
 extern unsigned long mips_rtc_get_time(void);
 
 #ifdef CONFIG_KGDB
@@ -185,7 +184,4 @@
 #endif
 #endif
 	mips_reboot_setup();
-
-	board_time_init = mips_time_init;
-	rtc_mips_get_time = mips_rtc_get_time;
 }
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index 5f70eaf..fad5897 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -35,7 +35,6 @@
 #include <asm/time.h>
 
 extern void mips_reboot_setup(void);
-extern void mips_time_init(void);
 
 static void __init serial_init(void);
 
@@ -52,8 +51,6 @@
 
 	serial_init ();
 
-	board_time_init = mips_time_init;
-
 	mips_reboot_setup();
 }
 
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index d012719..452c129 100644
--- a/arch/mips/mipssim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -36,7 +36,6 @@
 #include <asm/mips-boards/simint.h>
 
 
-extern void sim_time_init(void);
 static void __init serial_init(void);
 unsigned int _isbonito = 0;
 
@@ -54,7 +53,6 @@
 
 	serial_init();
 
-	board_time_init = sim_time_init;
 	pr_info("Linux started...\n");
 
 #ifdef CONFIG_MIPS_MT_SMP
diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c
index a0f5a5d..9a355e7 100644
--- a/arch/mips/mipssim/sim_time.c
+++ b/arch/mips/mipssim/sim_time.c
@@ -146,7 +146,7 @@
 	return count;
 }
 
-void __init sim_time_init(void)
+void __init plat_time_init(void)
 {
 	unsigned int est_freq, flags;
 
diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c
index 5bd7374..2ce298f 100644
--- a/arch/mips/philips/pnx8550/common/setup.c
+++ b/arch/mips/philips/pnx8550/common/setup.c
@@ -47,7 +47,6 @@
 extern void pnx8550_machine_power_off(void);
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
-extern void pnx8550_time_init(void);
 extern void rs_kgdb_hook(int tty_no);
 extern char *prom_getcmdline(void);
 
@@ -104,8 +103,6 @@
         _machine_halt = pnx8550_machine_halt;
         pm_power_off = pnx8550_machine_power_off;
 
-	board_time_init = pnx8550_time_init;
-
 	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
 	   Bit 1:Enable DAC Powerdown
 	  -> 0:DACs are enabled and are working normally
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
index 68def38..e818fd0 100644
--- a/arch/mips/philips/pnx8550/common/time.c
+++ b/arch/mips/philips/pnx8550/common/time.c
@@ -1,6 +1,7 @@
 /*
  * Copyright 2001, 2002, 2003 MontaVista Software Inc.
  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
  *
  * Common time service routines for MIPS machines. See
  * Documents/MIPS/README.txt.
@@ -46,16 +47,16 @@
 }
 
 /*
- * pnx8550_time_init() - it does the following things:
+ * plat_time_init() - it does the following things:
  *
- * 1) board_time_init() -
+ * 1) plat_time_init() -
  * 	a) (optional) set up RTC routines,
  *      b) (optional) calibrate and set the mips_hpt_frequency
  *	    (only needed if you intended to use cpu counter as timer interrupt
  *	     source)
  */
 
-void pnx8550_time_init(void)
+__init void plat_time_init(void)
 {
 	unsigned int             n;
 	unsigned int             m;
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
index e4cc548..c936756 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_setup.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -25,7 +25,6 @@
 #define MSP_BOARD_RESET_GPIO	9
 #endif
 
-extern void msp_timer_init(void);
 extern void msp_serial_setup(void);
 extern void pmctwiled_setup(void);
 
@@ -149,8 +148,6 @@
 	_machine_restart = msp_restart;
 	_machine_halt = msp_halt;
 	pm_power_off = msp_power_off;
-
-	board_time_init = msp_timer_init;
 }
 
 void __init prom_init(void)
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c
index 2a2beac5..f221d47 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_time.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c
@@ -36,7 +36,7 @@
 #include <msp_int.h>
 #include <msp_regs.h>
 
-void __init msp_timer_init(void)
+void __init plat_time_init(void)
 {
 	char    *endp, *s;
 	unsigned long cpu_rate = 0;
@@ -81,7 +81,6 @@
 	mips_hpt_frequency = cpu_rate/2;
 }
 
-
 void __init plat_timer_setup(struct irqaction *irq)
 {
 #ifdef CONFIG_IRQ_MSP_CIC
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 58862c8..56bf695 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -70,7 +70,7 @@
 }
 
 
-unsigned long m48t37y_get_time(void)
+unsigned long read_persistent_clock(void)
 {
 	unsigned int year, month, day, hour, min, sec;
 	unsigned long flags;
@@ -95,7 +95,7 @@
 	return mktime(year, month, day, hour, min, sec);
 }
 
-int m48t37y_set_time(unsigned long sec)
+int rtc_mips_set_time(unsigned long tim)
 {
 	struct rtc_time tm;
 	unsigned long flags;
@@ -138,7 +138,7 @@
 	setup_irq(7, irq);
 }
 
-void yosemite_time_init(void)
+void __init plat_time_init(void)
 {
 	mips_hpt_frequency = cpu_clock_freq / 2;
 mips_hpt_frequency = 33000000 * 3 * 5;
@@ -198,17 +198,6 @@
 	m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
 	if (!m48t37_base)
 		printk(KERN_ERR "Mapping the RTC failed\n");
-
-	rtc_mips_get_time = m48t37y_get_time;
-	rtc_mips_set_time = m48t37y_set_time;
-
-	write_seqlock(&xtime_lock);
-	xtime.tv_sec = m48t37y_get_time();
-	xtime.tv_nsec = 0;
-
-	set_normalized_timespec(&wall_to_monotonic,
-	                        -xtime.tv_sec, -xtime.tv_nsec);
-	write_sequnlock(&xtime_lock);
 }
 
 /* Not only time init but that's what the hook it's called through is named */
@@ -221,7 +210,6 @@
 
 void __init plat_mem_setup(void)
 {
-	board_time_init = yosemite_time_init;
 	late_time_init = py_late_time_init;
 
 	/* Add memory regions */
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index e7ce798..174f09e 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -51,7 +51,6 @@
 EXPORT_SYMBOL(ip22_do_break);
 
 extern void ip22_be_init(void) __init;
-extern void ip22_time_init(void) __init;
 
 void __init plat_mem_setup(void)
 {
@@ -59,7 +58,6 @@
 	char *cserial;
 
 	board_be_init = ip22_be_init;
-	ip22_time_init();
 
 	/* Init the INDY HPC I/O controller.  Need to call this before
 	 * fucking with the memory controller because it needs to know the
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index de3d018..0387c38 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -32,7 +32,7 @@
  * note that mktime uses month from 1 to 12 while to_tm
  * uses 0 to 11.
  */
-static unsigned long indy_rtc_get_time(void)
+unsigned long read_persistent_clock(void)
 {
 	unsigned int yrs, mon, day, hrs, min, sec;
 	unsigned int save_control;
@@ -60,7 +60,7 @@
 	return mktime(yrs + 1900, mon, day, hrs, min, sec);
 }
 
-static int indy_rtc_set_time(unsigned long tim)
+int rtc_mips_set_time(unsigned long tim)
 {
 	struct rtc_time tm;
 	unsigned int save_control;
@@ -128,7 +128,7 @@
 /*
  * Here we need to calibrate the cycle counter to at least be close.
  */
-static __init void indy_time_init(void)
+__init void plat_time_init(void)
 {
 	unsigned long r4k_ticks[3];
 	unsigned long r4k_tick;
@@ -207,12 +207,3 @@
 	/* setup irqaction */
 	setup_irq(SGI_TIMER_IRQ, irq);
 }
-
-void __init ip22_time_init(void)
-{
-	/* setup hookup functions */
-	rtc_mips_get_time = indy_rtc_get_time;
-	rtc_mips_set_time = indy_rtc_set_time;
-
-	board_time_init = indy_time_init;
-}
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
index af08c41..681b593 100644
--- a/arch/mips/sgi-ip27/ip27-init.c
+++ b/arch/mips/sgi-ip27/ip27-init.c
@@ -194,7 +194,6 @@
 	ioc3->eier = 0;
 }
 
-extern void ip27_time_init(void);
 extern void ip27_reboot_setup(void);
 
 void __init plat_mem_setup(void)
@@ -241,6 +240,4 @@
 	per_cpu_init();
 
 	set_io_port_base(IO_BASE);
-
-	board_time_init = ip27_time_init;
 }
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 3134616..9c1700e 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -123,7 +123,7 @@
 #include <asm/sn/sn0/hubio.h>
 #include <asm/pci/bridge.h>
 
-static __init unsigned long get_m48t35_time(void)
+unsigned long read_persistent_clock(void)
 {
         unsigned int year, month, date, hour, min, sec;
 	struct m48t35_rtc *rtc;
@@ -205,12 +205,10 @@
 	return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
 }
 
-void __init ip27_time_init(void)
+void __init plat_time_init(void)
 {
 	clocksource_mips.read = ip27_hpt_read;
 	mips_hpt_frequency = CYCLES_PER_SEC;
-	xtime.tv_sec = get_m48t35_time();
-	xtime.tv_nsec = 0;
 }
 
 void __init cpu_time_init(void)
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index bbba066..4125a5b 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -62,10 +62,15 @@
 }
 #endif
 
+unsigned long read_persistent_clock(void)
+{
+	return mc146818_get_cmos_time();
+}
+
 /* An arbitrary time; this can be decreased if reliability looks good */
 #define WAIT_MS 10
 
-void __init ip32_time_init(void)
+void __init plat_time_init(void)
 {
 	printk(KERN_INFO "Calibrating system timer... ");
 	write_c0_count(0);
@@ -85,11 +90,6 @@
 {
 	board_be_init = ip32_be_init;
 
-	rtc_mips_get_time = mc146818_get_cmos_time;
-	rtc_mips_set_mmss = mc146818_set_rtc_mmss;
-
-	board_time_init = ip32_time_init;
-
 #ifdef CONFIG_SGI_O2MACE_ETH
 	{
 		char *mac = ArcGetEnvironmentVariable("eaddr");
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 83572d8..8b3ef0e 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -69,7 +69,7 @@
 	return "SiByte " SIBYTE_BOARD_NAME;
 }
 
-void __init swarm_time_init(void)
+void __init plat_time_init(void)
 {
 #if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 	/* Setup HPT */
@@ -104,6 +104,44 @@
 	return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
 }
 
+enum swarm_rtc_type {
+	RTC_NONE,
+	RTC_XICOR,
+	RTC_M4LT81
+};
+
+enum swarm_rtc_type swarm_rtc_type;
+
+unsigned long read_persistent_clock(void)
+{
+	switch (swarm_rtc_type) {
+	case RTC_XICOR:
+		return xicor_get_time();
+
+	case RTC_M4LT81:
+		return m41t81_get_time();
+
+	case RTC_NONE:
+	default:
+		return mktime(2000, 1, 1, 0, 0, 0);
+	}
+}
+
+int rtc_mips_set_time(unsigned long sec)
+{
+	switch (swarm_rtc_type) {
+	case RTC_XICOR:
+		return xicor_set_time(sec);
+
+	case RTC_M4LT81:
+		return m41t81_set_time(sec);
+
+	case RTC_NONE:
+	default:
+		return -1;
+	}
+}
+
 void __init plat_mem_setup(void)
 {
 #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
@@ -116,20 +154,12 @@
 
 	panic_timeout = 5;  /* For debug.  */
 
-	board_time_init = swarm_time_init;
 	board_be_handler = swarm_be_handler;
 
-	if (xicor_probe()) {
-		printk("swarm setup: Xicor 1241 RTC detected.\n");
-		rtc_mips_get_time = xicor_get_time;
-		rtc_mips_set_time = xicor_set_time;
-	}
-
-	if (m41t81_probe()) {
-		printk("swarm setup: M41T81 RTC detected.\n");
-		rtc_mips_get_time = m41t81_get_time;
-		rtc_mips_set_time = m41t81_set_time;
-	}
+	if (xicor_probe())
+		swarm_rtc_type = RTC_XICOR;
+	if (m41t81_probe())
+		swarm_rtc_type = RTC_M4LT81;
 
 	printk("This kernel optimized for "
 #ifdef CONFIG_SIMULATION
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 44b1ae6..25cf646 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -313,7 +313,6 @@
 {
 	sni_pcimt_detect();
 	sni_pcimt_sc_init();
-	board_time_init = sni_cpu_time_init;
 	ioport_resource.end = sni_io_resource.end;
 #ifdef CONFIG_PCI
 	PCIBIOS_MIN_IO = 0x9000;
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 2480c47..3361bdd 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -263,7 +263,6 @@
 
 void __init sni_pcit_init(void)
 {
-	board_time_init = sni_cpu_time_init;
 	ioport_resource.end = sni_io_resource.end;
 #ifdef CONFIG_PCI
 	PCIBIOS_MIN_IO = 0x9000;
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index 28a11d8..94f115c 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -194,5 +194,4 @@
 {
 	set_io_port_base(SNI_PORT_BASE + 0x02000000);
 	ioport_resource.end += 0x02000000;
-	board_time_init = sni_cpu_time_init;
 }
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 20028fc..92452d6 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -4,6 +4,7 @@
 
 #include <asm/sni.h>
 #include <asm/time.h>
+#include <asm-generic/rtc.h>
 
 #define SNI_CLOCK_TICK_RATE     3686400
 #define SNI_COUNTER2_DIV        64
@@ -71,7 +72,7 @@
 /*
  * Here we need to calibrate the cycle counter to at least be close.
  */
-__init void sni_cpu_time_init(void)
+void __init plat_time_init(void)
 {
 	unsigned long r4k_ticks[3];
 	unsigned long r4k_tick;
@@ -146,3 +147,8 @@
 	        break;
 	}
 }
+
+unsigned long read_persistent_clock(void)
+{
+	return -1;
+}
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
index b18ed58..8ce0989 100644
--- a/arch/mips/tx4927/common/tx4927_setup.c
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -49,14 +49,11 @@
 
 #undef DEBUG
 
-void __init tx4927_time_init(void);
 void dump_cp0(char *key);
 
 
 void __init plat_mem_setup(void)
 {
-	board_time_init = tx4927_time_init;
-
 #ifdef CONFIG_TOSHIBA_RBTX4927
 	{
 		extern void toshiba_rbtx4927_setup(void);
@@ -65,20 +62,16 @@
 #endif
 }
 
-void __init tx4927_time_init(void)
+void __init plat_time_init(void)
 {
-
 #ifdef CONFIG_TOSHIBA_RBTX4927
 	{
 		extern void toshiba_rbtx4927_time_init(void);
 		toshiba_rbtx4927_time_init();
 	}
 #endif
-
-	return;
 }
 
-
 void __init plat_timer_setup(struct irqaction *irq)
 {
 	setup_irq(TX4927_IRQ_CPU_TIMER, irq);
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c
index 142abf4..ab40822 100644
--- a/arch/mips/tx4938/common/setup.c
+++ b/arch/mips/tx4938/common/setup.c
@@ -34,25 +34,16 @@
 #include <asm/tx4938/rbtx4938.h>
 
 extern void toshiba_rbtx4938_setup(void);
-extern void rbtx4938_time_init(void);
 
 void __init tx4938_setup(void);
-void __init tx4938_time_init(void);
 void dump_cp0(char *key);
 
 void __init
 plat_mem_setup(void)
 {
-	board_time_init = tx4938_time_init;
 	toshiba_rbtx4938_setup();
 }
 
-void __init
-tx4938_time_init(void)
-{
-	rbtx4938_time_init();
-}
-
 void __init plat_timer_setup(struct irqaction *irq)
 {
 	setup_irq(TX4938_IRQ_CPU_TIMER, irq);
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index f236b1f..304b406 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -39,7 +39,6 @@
 #include <asm/tx4938/spi.h>
 #include <asm/gpio.h>
 
-extern void rbtx4938_time_init(void) __init;
 extern char * __init prom_getcmdline(void);
 static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr);
 
@@ -856,7 +855,7 @@
 /* We use onchip r4k counter or TMR timer as our system wide timer
  * interrupt running at 100HZ. */
 
-void __init rbtx4938_time_init(void)
+void __init plat_time_init(void)
 {
 	mips_hpt_frequency = txx9_cpu_clock / 2;
 }
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index 4f97e0b..407cec2 100644
--- a/arch/mips/vr41xx/common/init.c
+++ b/arch/mips/vr41xx/common/init.c
@@ -36,7 +36,7 @@
 	iomem_resource.end = IO_MEM_RESOURCE_END;
 }
 
-static void __init setup_timer_frequency(void)
+void __init plat_time_init(void)
 {
 	unsigned long tclock;
 
@@ -53,16 +53,10 @@
 	setup_irq(TIMER_IRQ, irq);
 }
 
-static void __init timer_init(void)
-{
-	board_time_init = setup_timer_frequency;
-}
-
 void __init plat_mem_setup(void)
 {
 	vr41xx_calculate_clock_frequency();
 
-	timer_init();
 	iomem_resource_init();
 }
 
diff --git a/include/asm-mips/mach-bcm47xx/bcm47xx.h b/include/asm-mips/mach-bcm47xx/bcm47xx.h
index a2fb5e8..d008f47 100644
--- a/include/asm-mips/mach-bcm47xx/bcm47xx.h
+++ b/include/asm-mips/mach-bcm47xx/bcm47xx.h
@@ -22,6 +22,4 @@
 /* SSB bus */
 extern struct ssb_bus ssb_bcm47xx;
 
-extern void bcm47xx_time_init(void);
-
 #endif /* __ASM_BCM47XX_H */
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index a632cef..74ab331 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -26,15 +26,13 @@
 extern spinlock_t rtc_lock;
 
 /*
- * RTC ops.  By default, they point to no-RTC functions.
- *	rtc_mips_get_time - mktime(year, mon, day, hour, min, sec) in seconds.
+ * RTC ops.  By default, they point to weak no-op RTC functions.
  *	rtc_mips_set_time - reverse the above translation and set time to RTC.
  *	rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need
  *			to be set.  Used by RTC sync-up.
  */
-extern unsigned long (*rtc_mips_get_time)(void);
-extern int (*rtc_mips_set_time)(unsigned long);
-extern int (*rtc_mips_set_mmss)(unsigned long);
+extern int rtc_mips_set_time(unsigned long);
+extern int rtc_mips_set_mmss(unsigned long);
 
 /*
  * Timer interrupt functions.
@@ -75,11 +73,9 @@
 
 /*
  * board specific routines required by time_init().
- * board_time_init is defaulted to NULL and can remain so.
- * plat_timer_setup must be setup properly in machine setup routine.
  */
 struct irqaction;
-extern void (*board_time_init)(void);
+extern void plat_time_init(void);
 extern void plat_timer_setup(struct irqaction *irq);
 
 /*