diff --git a/arch/arm/mach-picoxcell/common.h b/arch/arm/mach-picoxcell/common.h
index 237fb3bcbd04..481b42a4ef15 100644
--- a/arch/arm/mach-picoxcell/common.h
+++ b/arch/arm/mach-picoxcell/common.h
@@ -12,4 +12,6 @@
 
 #include <asm/mach/time.h>
 
+extern void dw_apb_timer_init(void);
+
 #endif /* __PICOXCELL_COMMON_H__ */
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index e7042bc5c7d2..e54ca1062d8e 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -21,6 +21,12 @@
 #define APBT_MIN_PERIOD			4
 #define APBT_MIN_DELTA_USEC		200
 
+#define APBTMR_N_LOAD_COUNT		0x00
+#define APBTMR_N_CURRENT_VALUE		0x04
+#define APBTMR_N_CONTROL		0x08
+#define APBTMR_N_EOI			0x0c
+#define APBTMR_N_INT_STATUS		0x10
+
 #define APBTMRS_INT_STATUS		0xa0
 #define APBTMRS_EOI			0xa4
 #define APBTMRS_RAW_INT_STATUS		0xa8
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index a97b4065dacf..d9a1e8d51751 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -55,15 +55,6 @@ static void add_clockevent(struct device_node *event_timer)
 	dw_apb_clockevent_register(ced);
 }
 
-static void __iomem *sched_io_base;
-
-/* This is actually same as __apbt_read_clocksource(), but with
-   different interface */
-static u32 read_sched_clock_sptimer(void)
-{
-	return ~__raw_readl(sched_io_base + APBTMR_N_CURRENT_VALUE);
-}
-
 static void add_clocksource(struct device_node *source_timer)
 {
 	void __iomem *iobase;
@@ -78,28 +69,42 @@ static void add_clocksource(struct device_node *source_timer)
 
 	dw_apb_clocksource_start(cs);
 	dw_apb_clocksource_register(cs);
+}
 
-	sched_io_base = iobase;
-	setup_sched_clock(read_sched_clock_sptimer, 32, rate);
+static void __iomem *sched_io_base;
+
+static u32 read_sched_clock(void)
+{
+	return __raw_readl(sched_io_base);
+}
+
+static const struct of_device_id sptimer_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-rtc" },
+	{ .compatible = "snps,dw-apb-timer-sp" },
+	{ /* Sentinel */ },
+};
+
+static void init_sched_clock(void)
+{
+	struct device_node *sched_timer;
+	u32 rate;
+
+	sched_timer = of_find_matching_node(NULL, sptimer_ids);
+	if (!sched_timer)
+		panic("No RTC for sched clock to use");
+
+	timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+	of_node_put(sched_timer);
+
+	setup_sched_clock(read_sched_clock, 32, rate);
 }
 
 static const struct of_device_id osctimer_ids[] __initconst = {
 	{ .compatible = "picochip,pc3x2-timer" },
 	{ .compatible = "snps,dw-apb-timer-osc" },
-	{ .compatible = "snps,dw-apb-timer-sp" },
-	{  /* Sentinel */ },
+	{},
 };
 
-/*
-   You don't have to use dw_apb_timer for scheduler clock,
-   this should also work fine on arm:
-
-  twd_local_timer_of_register();
-  arch_timer_of_register();
-  arch_timer_sched_clock_init();
-*/
-
-
 void __init dw_apb_timer_init(void)
 {
 	struct device_node *event_timer, *source_timer;
@@ -114,6 +119,7 @@ void __init dw_apb_timer_init(void)
 		panic("No timer for clocksource");
 	add_clocksource(source_timer);
 
-	of_node_put(event_timer);
 	of_node_put(source_timer);
+
+	init_sched_clock();
 }
diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h
index de0904e38f33..b1cd9597c241 100644
--- a/include/linux/dw_apb_timer.h
+++ b/include/linux/dw_apb_timer.h
@@ -17,12 +17,6 @@
 #include <linux/clocksource.h>
 #include <linux/interrupt.h>
 
-#define APBTMR_N_LOAD_COUNT		0x00
-#define APBTMR_N_CURRENT_VALUE		0x04
-#define APBTMR_N_CONTROL		0x08
-#define APBTMR_N_EOI			0x0c
-#define APBTMR_N_INT_STATUS		0x10
-
 #define APBTMRS_REG_SIZE       0x14
 
 struct dw_apb_timer {