[PATCH 10/14] at91: switch st timer to early platform devices

Jean-Christophe PLAGNIOL-VILLARD plagnioj at jcrosoft.com
Mon Apr 25 14:31:20 EDT 2011


this will allow to specify the resources per soc
and have only one time init for all boards except x40

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
Cc: Patrice Vilchez <patrice.vilchez at atmel.com>
---
 arch/arm/mach-at91/at91rm9200.c       |    6 +
 arch/arm/mach-at91/at91rm9200_time.c  |  271 +++++++++++++++++++++++---------
 arch/arm/mach-at91/board-1arm.c       |    2 +-
 arch/arm/mach-at91/board-carmeva.c    |    2 +-
 arch/arm/mach-at91/board-cpuat91.c    |    2 +-
 arch/arm/mach-at91/board-csb337.c     |    2 +-
 arch/arm/mach-at91/board-csb637.c     |    2 +-
 arch/arm/mach-at91/board-eb9200.c     |    2 +-
 arch/arm/mach-at91/board-ecbat91.c    |    2 +-
 arch/arm/mach-at91/board-eco920.c     |    2 +-
 arch/arm/mach-at91/board-kafa.c       |    2 +-
 arch/arm/mach-at91/board-kb9202.c     |    2 +-
 arch/arm/mach-at91/board-picotux200.c |    2 +-
 arch/arm/mach-at91/board-rm9200dk.c   |    2 +-
 arch/arm/mach-at91/board-rm9200ek.c   |    2 +-
 arch/arm/mach-at91/board-yl-9200.c    |    2 +-
 arch/arm/mach-at91/generic.h          |    2 +-
 arch/arm/mach-at91/soc.c              |   21 +++-
 arch/arm/mach-at91/soc.h              |    1 +
 19 files changed, 237 insertions(+), 92 deletions(-)

diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index e80d544..7b9d3a4 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -378,6 +378,11 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0	/* Advanced Interrupt Controller (IRQ6) */
 };
 
+struct at91_dev_resource at91rm9200_st __initdata = {
+	.mmio_base	= AT91_ST,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91rm9200_soc = {
 	.name = "at91rm9200",
 	.default_irq_priority = at91rm9200_default_irq_priority,
@@ -386,4 +391,5 @@ struct at91_soc __initdata at91rm9200_soc = {
 		.resource = at91rm9200_pios,
 		.num_resources = ARRAY_SIZE(at91rm9200_pios),
 	},
+	.st = &at91rm9200_st,
 };
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 1dd69c8..538ee40 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -1,8 +1,9 @@
 /*
  * linux/arch/arm/mach-at91/at91rm9200_time.c
  *
- *  Copyright (C) 2003 SAN People
- *  Copyright (C) 2003 ATMEL
+ * Copyright (C) 2003 SAN People
+ * Copyright (C) 2003 ATMEL
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,30 +21,58 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/clockchips.h>
-
-#include <asm/mach/time.h>
+#include <linux/slab.h>
 
 #include <mach/at91_st.h>
 
-static unsigned long last_crtr;
-static u32 irqmask;
-static struct clock_event_device clkevt;
+struct at91_st_data {
+	void __iomem *mapbase;
+	unsigned long last_crtr;
+	u32 irqmask;
+	struct clock_event_device ced;
+	struct clocksource cs;
+	struct irqaction irqaction;
+	struct platform_device *pdev;
+};
+
+static inline unsigned int at91_st_read(struct at91_st_data *data,
+					 unsigned int reg_offset)
+{
+	return __raw_readl(data->mapbase + reg_offset);
+}
+
+static inline void at91_st_write(struct at91_st_data *data,
+			unsigned int reg_offset, unsigned long value)
+{
+	__raw_writel(value, data->mapbase + reg_offset);
+}
+
+static struct at91_st_data *cs_to_at91_st(struct clocksource *cs)
+{
+	return container_of(cs, struct at91_st_data, cs);
+}
+
+static struct at91_st_data *ced_to_at91_st(struct clock_event_device *ced)
+{
+	return container_of(ced, struct at91_st_data, ced);
+}
 
 /*
  * The ST_CRTR is updated asynchronously to the master clock ... but
  * the updates as seen by the CPU don't seem to be strictly monotonic.
  * Waiting until we read the same value twice avoids glitching.
  */
-static inline unsigned long read_CRTR(void)
+static inline unsigned long read_CRTR(struct at91_st_data *data)
 {
 	unsigned long x1, x2;
 
-	x1 = at91_sys_read(AT91_ST_CRTR);
+	x1 = at91_st_read(data, AT91_ST_CRTR);
 	do {
-		x2 = at91_sys_read(AT91_ST_CRTR);
+		x2 = at91_st_read(data, AT91_ST_CRTR);
 		if (x1 == x2)
 			break;
 		x1 = x2;
@@ -54,9 +83,13 @@ static inline unsigned long read_CRTR(void)
 /*
  * IRQ handler for the timer.
  */
-static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
+static irqreturn_t at91_st_interrupt(int irq, void *dev_id)
 {
-	u32	sr = at91_sys_read(AT91_ST_SR) & irqmask;
+	struct at91_st_data *data = (struct at91_st_data*)dev_id;
+	struct clock_event_device *ced = &data->ced;
+	u32 sr;
+
+	sr = at91_st_read(data, AT91_ST_SR) & data->irqmask;
 
 	/*
 	 * irqs should be disabled here, but as the irq is shared they are only
@@ -66,17 +99,17 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 
 	/* simulate "oneshot" timer with alarm */
 	if (sr & AT91_ST_ALMS) {
-		clkevt.event_handler(&clkevt);
+		ced->event_handler(ced);
 		return IRQ_HANDLED;
 	}
 
 	/* periodic mode should handle delayed ticks */
 	if (sr & AT91_ST_PITS) {
-		u32	crtr = read_CRTR();
+		u32	crtr = read_CRTR(data);
 
-		while (((crtr - last_crtr) & AT91_ST_CRTV) >= LATCH) {
-			last_crtr += LATCH;
-			clkevt.event_handler(&clkevt);
+		while (((crtr - data->last_crtr) & AT91_ST_CRTV) >= LATCH) {
+			data->last_crtr += LATCH;
+			ced->event_handler(ced);
 		}
 		return IRQ_HANDLED;
 	}
@@ -85,60 +118,51 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
-static struct irqaction at91rm9200_timer_irq = {
-	.name		= "at91_tick",
-	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= at91rm9200_timer_interrupt
-};
-
-static cycle_t read_clk32k(struct clocksource *cs)
+static cycle_t at91_st_clocksource_read(struct clocksource *cs)
 {
-	return read_CRTR();
-}
+	struct at91_st_data *data = cs_to_at91_st(cs);
 
-static struct clocksource clk32k = {
-	.name		= "32k_counter",
-	.rating		= 150,
-	.read		= read_clk32k,
-	.mask		= CLOCKSOURCE_MASK(20),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
+	return read_CRTR(data);
+}
 
-static void
-clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+static void at91_st_clock_event_mode(enum clock_event_mode mode,
+				      struct clock_event_device *dev)
 {
+	struct at91_st_data *data = ced_to_at91_st(dev);
+
 	/* Disable and flush pending timer interrupts */
 	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
-	(void) at91_sys_read(AT91_ST_SR);
+	(void) at91_st_read(data, AT91_ST_SR);
 
-	last_crtr = read_CRTR();
+	data->last_crtr = read_CRTR(data);
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		/* PIT for periodic irqs; fixed rate of 1/HZ */
-		irqmask = AT91_ST_PITS;
-		at91_sys_write(AT91_ST_PIMR, LATCH);
+		data->irqmask = AT91_ST_PITS;
+		at91_st_write(data, AT91_ST_PIMR, LATCH);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		/* ALM for oneshot irqs, set by next_event()
 		 * before 32 seconds have passed
 		 */
-		irqmask = AT91_ST_ALMS;
-		at91_sys_write(AT91_ST_RTAR, last_crtr);
+		data->irqmask = AT91_ST_ALMS;
+		at91_st_write(data, AT91_ST_RTAR, data->last_crtr);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_RESUME:
-		irqmask = 0;
+		data->irqmask = 0;
 		break;
 	}
-	at91_sys_write(AT91_ST_IER, irqmask);
+	at91_st_write(data, AT91_ST_IER, data->irqmask);
 }
 
-static int
-clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
+static int at91_st_clock_event_next(unsigned long delta,
+				   struct clock_event_device *ced)
 {
-	u32		alm;
-	int		status = 0;
+	struct at91_st_data *data = ced_to_at91_st(ced);
+	u32 alm;
+	int status = 0;
 
 	BUG_ON(delta < 2);
 
@@ -151,59 +175,154 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 	 * with the value then held in CRTR ... which would mean the match
 	 * wouldn't trigger until 32 seconds later, after CRTR wraps.
 	 */
-	alm = read_CRTR();
+	alm = read_CRTR(data);
 
 	/* Cancel any pending alarm; flush any pending IRQ */
-	at91_sys_write(AT91_ST_RTAR, alm);
-	(void) at91_sys_read(AT91_ST_SR);
+	at91_st_write(data, AT91_ST_RTAR, alm);
+	(void) at91_st_read(data, AT91_ST_SR);
 
 	/* Schedule alarm by writing RTAR. */
 	alm += delta;
-	at91_sys_write(AT91_ST_RTAR, alm);
+	at91_st_write(data, AT91_ST_RTAR, alm);
 
 	return status;
 }
 
-static struct clock_event_device clkevt = {
-	.name		= "at91_tick",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
-	.rating		= 150,
-	.set_next_event	= clkevt32k_next_event,
-	.set_mode	= clkevt32k_mode,
-};
+static void at91_st_register_clockevent(struct at91_st_data *data)
+{
+	struct clock_event_device *ced = &data->ced;
 
-/*
- * ST (system timer) module supports both clockevents and clocksource.
- */
-void __init at91rm9200_timer_init(void)
+	memset(ced, 0, sizeof(*ced));
+
+	ced->name = "at91_tick";
+	ced->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	ced->shift = 32;
+	ced->rating = 150;
+	ced->set_next_event = at91_st_clock_event_next;
+	ced->set_mode = at91_st_clock_event_mode;
+	ced->mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, ced->shift);
+	ced->max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, ced);
+	ced->min_delta_ns = clockevent_delta2ns(2, ced) + 1;
+	ced->cpumask = cpumask_of(0);
+
+	dev_info(&data->pdev->dev, "used for clock events\n");
+
+	clockevents_register_device(ced);
+}
+
+static int at91_st_register_clocksource(struct at91_st_data *data)
 {
+	struct clocksource *cs = &data->cs;
+
+	cs->name = "32k_counter";
+	cs->rating = 150;
+	cs->read = at91_st_clocksource_read;
+	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+	cs->mask = CLOCKSOURCE_MASK(20);
+
+	dev_info(&data->pdev->dev, "used as clock source\n");
+
+	clocksource_register_hz(cs, AT91_SLOW_CLOCK);
+
+	return 0;
+}
+
+static int at91_st_setup(struct at91_st_data *data,
+			  struct platform_device *pdev)
+{
+	struct resource	*res;
+	int		irq;
+	int		ret = -ENXIO;
+
+	memset(data, 0, sizeof(struct at91_st_data));
+	data->pdev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		goto err0;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq\n");
+		goto err0;
+	}
+
+	/* map memory, let mapbase point to our channel */
+	data->mapbase = (void * __iomem)(res->start + AT91_VA_BASE_SYS);
+
+	/* request irq using setup_irq() (too early for request_irq()) */
+	data->irqaction.name = "at91_tick";
+	data->irqaction.handler = at91_st_interrupt;
+	data->irqaction.dev_id = data;
+	data->irqaction.flags = IRQF_SHARED | IRQF_DISABLED |
+				IRQF_TIMER  | IRQF_IRQPOLL;
+
 	/* Disable all timer interrupts, and clear any pending ones */
 	at91_sys_write(AT91_ST_IDR,
 		AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
 	(void) at91_sys_read(AT91_ST_SR);
 
-	/* Make IRQs happen for the system timer */
-	setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
-
 	/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
 	 * directly for the clocksource and all clockevents, after adjusting
 	 * its prescaler from the 1 Hz default.
 	 */
 	at91_sys_write(AT91_ST_RTMR, 1);
 
-	/* Setup timer clockevent, with minimum of two ticks (important!!) */
-	clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
-	clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
-	clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
-	clkevt.cpumask = cpumask_of(0);
-	clockevents_register_device(&clkevt);
+	/*
+	 * Register clocksource.  The high order bits of PIV are unused,
+	 * so this isn't a 32-bit counter unless we get clockevent irqs.
+	 */
+	at91_st_register_clocksource(data);
+
+	/* Set up irq handler */
+	setup_irq(irq, &data->irqaction);
 
-	/* register clocksource */
-	clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
+	/* Set up and register clockevents */
+	at91_st_register_clockevent(data);
+
+	return 0;
+
+err0:
+	return ret;
+}
+
+static int __devinit at91_st_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct at91_st_data *data;
+
+	if (!is_early_platform_device(pdev)) {
+		pr_info("at91_st.%d: call via non early plaform\n", pdev->id);
+		return 0;
+	}
+
+	data = kmalloc(sizeof(struct at91_st_data), GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	ret = at91_st_setup(data, pdev);
+
+	if (ret)
+		kfree(data);
+
+	return ret;
 }
 
-struct sys_timer at91rm9200_timer = {
-	.init		= at91rm9200_timer_init,
+static int __devexit at91_st_remove(struct platform_device *pdev)
+{
+	return -EBUSY; /* cannot unregister clockevent and clocksource */
+}
+
+static struct platform_driver at91_st_device_driver = {
+	.probe		= at91_st_probe,
+	.remove		= __devexit_p(at91_st_remove),
+	.driver		= {
+		.name	= "at91_st",
+	}
 };
 
+early_platform_init("earlytimer", &at91_st_device_driver);
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index ba08329..b487dff 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -97,7 +97,7 @@ static void __init onearm_board_init(void)
 MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
 	/* Maintainer: Lennert Buytenhek <buytenh at wantstofly.org> */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= onearm_map_io,
 	.init_irq	= onearm_init_irq,
 	.init_machine	= onearm_board_init,
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index cb888cf..d2178fd 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -163,7 +163,7 @@ static void __init carmeva_board_init(void)
 MACHINE_START(CARMEVA, "Carmeva")
 	/* Maintainer: Conitec Datasystems */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= carmeva_map_io,
 	.init_irq	= carmeva_init_irq,
 	.init_machine	= carmeva_board_init,
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index 33ddbfa..1afdad4 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -180,7 +180,7 @@ static void __init cpuat91_board_init(void)
 MACHINE_START(CPUAT91, "Eukrea")
 	/* Maintainer: Eric Benard - EUKREA Electromatique */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= cpuat91_map_io,
 	.init_irq	= cpuat91_init_irq,
 	.init_machine	= cpuat91_board_init,
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 354e85e..1a61446 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -258,7 +258,7 @@ static void __init csb337_board_init(void)
 MACHINE_START(CSB337, "Cogent CSB337")
 	/* Maintainer: Bill Gatliff */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= csb337_map_io,
 	.init_irq	= csb337_init_irq,
 	.init_machine	= csb337_board_init,
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index 9bff91f..efe7c39 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -139,7 +139,7 @@ static void __init csb637_board_init(void)
 MACHINE_START(CSB637, "Cogent CSB637")
 	/* Maintainer: Bill Gatliff */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= csb637_map_io,
 	.init_irq	= csb637_init_irq,
 	.init_machine	= csb637_board_init,
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 8101ef0..9643bf5 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -121,7 +121,7 @@ static void __init eb9200_board_init(void)
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= eb9200_map_io,
 	.init_irq	= eb9200_init_irq,
 	.init_machine	= eb9200_board_init,
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 7fb26f9..5a1537a 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -173,7 +173,7 @@ static void __init ecb_at91board_init(void)
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
 	/* Maintainer: emQbit.com */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= ecb_at91map_io,
 	.init_irq	= ecb_at91init_irq,
 	.init_machine	= ecb_at91board_init,
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index 9c979bb..efd160d 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -135,7 +135,7 @@ static void __init eco920_board_init(void)
 MACHINE_START(ECO920, "eco920")
 	/* Maintainer: Sascha Hauer */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= eco920_map_io,
 	.init_irq	= eco920_init_irq,
 	.init_machine	= eco920_board_init,
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index cf7e7a0..b20bd84 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -99,7 +99,7 @@ static void __init kafa_board_init(void)
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
 	/* Maintainer: Sergei Sharonov */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= kafa_map_io,
 	.init_irq	= kafa_init_irq,
 	.init_machine	= kafa_board_init,
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index a56cdee..570b00d 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -140,7 +140,7 @@ static void __init kb9202_board_init(void)
 MACHINE_START(KB9200, "KB920x")
 	/* Maintainer: KwikByte, Inc. */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= kb9202_map_io,
 	.init_irq	= kb9202_init_irq,
 	.init_machine	= kb9202_board_init,
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 3267b95..5184964 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -124,7 +124,7 @@ static void __init picotux200_board_init(void)
 MACHINE_START(PICOTUX2XX, "picotux 200")
 	/* Maintainer: Kleinhenz Elektronik GmbH */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= picotux200_map_io,
 	.init_irq	= picotux200_init_irq,
 	.init_machine	= picotux200_board_init,
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index c14f2c2..d715327 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -228,7 +228,7 @@ static void __init dk_board_init(void)
 MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
 	/* Maintainer: SAN People/Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= dk_map_io,
 	.init_irq	= dk_init_irq,
 	.init_machine	= dk_board_init,
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index ffd69c0..755929c 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -194,7 +194,7 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
 	/* Maintainer: SAN People/Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= ek_map_io,
 	.init_irq	= ek_init_irq,
 	.init_machine	= ek_board_init,
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index e9ca130..16bb91d 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -599,7 +599,7 @@ static void __init yl9200_board_init(void)
 MACHINE_START(YL9200, "uCdragon YL-9200")
 	/* Maintainer: S.Birtles */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
+	.timer		= &at91_timer,
 	.map_io		= yl9200_map_io,
 	.init_irq	= yl9200_init_irq,
 	.init_machine	= yl9200_board_init,
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 1cfe696..eb01942 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -22,7 +22,7 @@ extern void __init at91_aic_init(unsigned int priority[]);
 
  /* Timer */
 struct sys_timer;
-extern struct sys_timer at91rm9200_timer;
+extern struct sys_timer at91_timer;
 extern struct sys_timer at91_timer;
 extern struct sys_timer at91x40_timer;
 
diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c
index 7b44be2..1b05997 100644
--- a/arch/arm/mach-at91/soc.c
+++ b/arch/arm/mach-at91/soc.c
@@ -229,18 +229,37 @@ static struct platform_device at91_pit_device = {
 	.num_resources	= ARRAY_SIZE(pit_resources),
 };
 
+/*
+ * ST (system timer) module supports both clockevents and clocksource.
+ */
+static struct resource st_resources[] = {
+	[0] = RES_MEM(SZ_256),
+	[1] = RES_IRQ(),
+};
+
+static struct platform_device at91_st_device = {
+	.name		= "at91_st",
+	.id		= 0,
+	.resource	= st_resources,
+	.num_resources	= ARRAY_SIZE(st_resources),
+};
+
 static void __init at91_timer_init(void)
 {
 	struct at91_dev_resource *res;
 	struct platform_device *pdev;
 	struct resource *r;
 
-	BUG_ON(!current_soc.pit);
+	BUG_ON(!current_soc.pit && !current_soc.st);
 
 	if (current_soc.pit) {
 		r = pit_resources;
 		res = current_soc.pit;
 		pdev = &at91_pit_device;
+	} else {
+		r = st_resources;
+		res = current_soc.st;
+		pdev = &at91_st_device;
 	}
 
 	set_resource_mem(&r[0], res->mmio_base);
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index 8df07a2..a60ac0a 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -14,6 +14,7 @@ struct at91_soc {
 
 	struct at91_dev_resource_array gpio;
 	struct at91_dev_resource *pit;
+	struct at91_dev_resource *st;
 
 	void (*init)(unsigned long main_clock);
 };
-- 
1.7.4.1




More information about the linux-arm-kernel mailing list