[PATCH 09/14] at91: switch pit timer to early platform devices

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


this will allow to specify the resources per soc

as the 5series use a different start address for the pit

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/at572d940hf.c           |    6 +
 arch/arm/mach-at91/at91cap9.c              |    6 +
 arch/arm/mach-at91/at91sam9260.c           |    6 +
 arch/arm/mach-at91/at91sam9261.c           |    6 +
 arch/arm/mach-at91/at91sam9263.c           |    6 +
 arch/arm/mach-at91/at91sam926x_time.c      |  277 +++++++++++++++++++++-------
 arch/arm/mach-at91/at91sam9g45.c           |    6 +
 arch/arm/mach-at91/at91sam9rl.c            |    6 +
 arch/arm/mach-at91/board-afeb-9260v1.c     |    2 +-
 arch/arm/mach-at91/board-at572d940hf_ek.c  |    2 +-
 arch/arm/mach-at91/board-cam60.c           |    2 +-
 arch/arm/mach-at91/board-cap9adk.c         |    2 +-
 arch/arm/mach-at91/board-cpu9krea.c        |    2 +-
 arch/arm/mach-at91/board-flexibity.c       |    2 +-
 arch/arm/mach-at91/board-foxg20.c          |    2 +-
 arch/arm/mach-at91/board-gsia18s.c         |    2 +-
 arch/arm/mach-at91/board-neocore926.c      |    2 +-
 arch/arm/mach-at91/board-pcontrol-g20.c    |    2 +-
 arch/arm/mach-at91/board-qil-a9260.c       |    2 +-
 arch/arm/mach-at91/board-sam9-l9260.c      |    2 +-
 arch/arm/mach-at91/board-sam9260ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9261ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9263ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9g20ek.c       |    4 +-
 arch/arm/mach-at91/board-sam9m10g45ek.c    |    2 +-
 arch/arm/mach-at91/board-sam9rlek.c        |    2 +-
 arch/arm/mach-at91/board-snapper9260.c     |    2 +-
 arch/arm/mach-at91/board-stamp9g20.c       |    4 +-
 arch/arm/mach-at91/board-usb-a926x.c       |    4 +-
 arch/arm/mach-at91/devices.c               |    4 +-
 arch/arm/mach-at91/generic.h               |    2 +-
 arch/arm/mach-at91/include/mach/at91_pit.h |    8 +-
 arch/arm/mach-at91/soc.c                   |   42 +++++
 arch/arm/mach-at91/soc.h                   |    1 +
 34 files changed, 327 insertions(+), 97 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c
index b788861..66405af 100644
--- a/arch/arm/mach-at91/at572d940hf.c
+++ b/arch/arm/mach-at91/at572d940hf.c
@@ -417,6 +417,11 @@ static unsigned int at572d940hf_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
+struct at91_dev_resource at572d940hf_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at572d940hf_soc = {
 	.name = "at572d940hf",
 	.default_irq_priority = at572d940hf_default_irq_priority,
@@ -425,4 +430,5 @@ struct at91_soc __initdata at572d940hf_soc = {
 		.resource = at572d940hf_pios,
 		.num_resources = ARRAY_SIZE(at572d940hf_pios),
 	},
+	.pit = &at572d940hf_pit,
 };
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index f60ec74..dd5e858 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -420,6 +420,11 @@ static unsigned int at91cap9_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ1) */
 };
 
+struct at91_dev_resource at91cap9_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91cap9_soc = {
 	.name = "at91cap9",
 	.default_irq_priority = at91cap9_default_irq_priority,
@@ -428,4 +433,5 @@ struct at91_soc __initdata at91cap9_soc = {
 		.resource = at91cap9_pios,
 		.num_resources = ARRAY_SIZE(at91cap9_pios),
 	},
+	.pit = &at91cap9_pit,
 };
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 4859231..0567556b 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -409,6 +409,11 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
+struct at91_dev_resource at91sam9260_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91sam9260_soc = {
 	.name = "at91sam9260",
 	.default_irq_priority = at91sam9260_default_irq_priority,
@@ -417,4 +422,5 @@ struct at91_soc __initdata at91sam9260_soc = {
 		.resource = at91sam9260_pios,
 		.num_resources = ARRAY_SIZE(at91sam9260_pios),
 	},
+	.pit = &at91sam9260_pit,
 };
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 5a3f68b..603c6fe 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -375,6 +375,11 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
+struct at91_dev_resource at91sam9261_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91sam9261_soc = {
 	.name = "at91sam9261",
 	.default_irq_priority = at91sam9261_default_irq_priority,
@@ -383,4 +388,5 @@ struct at91_soc __initdata at91sam9261_soc = {
 		.resource = at91sam9261_pios,
 		.num_resources = ARRAY_SIZE(at91sam9261_pios),
 	},
+	.pit = &at91sam9261_pit,
 };
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 9a0b3b4..e7ff884 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -384,6 +384,11 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ1) */
 };
 
+struct at91_dev_resource at91sam9263_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91sam9263_soc = {
 	.name = "at91sam9263",
 	.default_irq_priority = at91sam9263_default_irq_priority,
@@ -392,4 +397,5 @@ struct at91_soc __initdata at91sam9263_soc = {
 		.resource = at91sam9263_pios,
 		.num_resources = ARRAY_SIZE(at91sam9263_pios),
 	},
+	.pit = &at91sam9263_pit,
 };
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 4ba8549..82ddaa7 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -4,69 +4,96 @@
  * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
  * Revision	 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
  * Converted to ClockSource/ClockEvents by David Brownell.
+ * 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 version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
-
-#include <asm/mach/time.h>
+#include <linux/slab.h>
 
 #include <mach/at91_pit.h>
 
+struct at91_pit_data {
+	void __iomem *mapbase;
+	u32 pit_cycle;		/* write-once */
+	u32 pit_cnt;		/* access only w/system irq blocked */
+	struct clock_event_device ced;
+	struct clocksource cs;
+	struct irqaction irqaction;
+	struct platform_device *pdev;
+};
 
 #define PIT_CPIV(x)	((x) & AT91_PIT_CPIV)
 #define PIT_PICNT(x)	(((x) & AT91_PIT_PICNT) >> 20)
 
-static u32 pit_cycle;		/* write-once */
-static u32 pit_cnt;		/* access only w/system irq blocked */
+static inline unsigned int at91_pit_read(struct at91_pit_data *data,
+					 unsigned int reg_offset)
+{
+	return __raw_readl(data->mapbase + reg_offset);
+}
+
+static inline void at91_pit_write(struct at91_pit_data *data,
+			unsigned int reg_offset, unsigned long value)
+{
+	__raw_writel(value, data->mapbase + reg_offset);
+}
 
+static struct at91_pit_data *cs_to_at91_pit(struct clocksource *cs)
+{
+	return container_of(cs, struct at91_pit_data, cs);
+}
+
+static struct at91_pit_data *ced_to_at91_pit(struct clock_event_device *ced)
+{
+	return container_of(ced, struct at91_pit_data, ced);
+}
 
 /*
  * Clocksource:  just a monotonic counter of MCK/16 cycles.
  * We don't care whether or not PIT irqs are enabled.
  */
-static cycle_t read_pit_clk(struct clocksource *cs)
+static cycle_t at91_pit_clocksource_read(struct clocksource *cs)
 {
+	struct at91_pit_data *data = cs_to_at91_pit(cs);
 	unsigned long flags;
 	u32 elapsed;
 	u32 t;
 
 	raw_local_irq_save(flags);
-	elapsed = pit_cnt;
-	t = at91_sys_read(AT91_PIT_PIIR);
+	elapsed = data->pit_cnt;
+	t = at91_pit_read(data, AT91_PIT_PIIR);
 	raw_local_irq_restore(flags);
 
-	elapsed += PIT_PICNT(t) * pit_cycle;
+	elapsed += PIT_PICNT(t) * data->pit_cycle;
 	elapsed += PIT_CPIV(t);
 	return elapsed;
 }
 
-static struct clocksource pit_clk = {
-	.name		= "pit",
-	.rating		= 175,
-	.read		= read_pit_clk,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 
 /*
  * Clockevent device:  interrupts every 1/HZ (== pit_cycles * MCK/16)
  */
-static void
-pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+static void at91_pit_clock_event_mode(enum clock_event_mode mode,
+				      struct clock_event_device *dev)
 {
+	struct at91_pit_data *data = ced_to_at91_pit(dev);
+	u32 tmp;
+
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		/* update clocksource counter */
-		pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
-		at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
-				| AT91_PIT_PITIEN);
+		tmp = PIT_PICNT(at91_pit_read(data, AT91_PIT_PIVR));
+		data->pit_cnt += data->pit_cycle * tmp;
+		at91_pit_write(data, AT91_PIT_MR, (data->pit_cycle - 1)
+				| AT91_PIT_PITEN | AT91_PIT_PITIEN);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		BUG();
@@ -74,27 +101,22 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
 		/* disable irq, leaving the clocksource active */
-		at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+		at91_pit_write(data, AT91_PIT_MR,
+				(data->pit_cycle - 1) | AT91_PIT_PITEN);
 		break;
 	case CLOCK_EVT_MODE_RESUME:
 		break;
 	}
 }
 
-static struct clock_event_device pit_clkevt = {
-	.name		= "pit",
-	.features	= CLOCK_EVT_FEAT_PERIODIC,
-	.shift		= 32,
-	.rating		= 100,
-	.set_mode	= pit_clkevt_mode,
-};
-
 
 /*
  * IRQ handler for the timer.
  */
-static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
+static irqreturn_t at91_pit_interrupt(int irq, void *dev_id)
 {
+	struct at91_pit_data *data = (struct at91_pit_data*)dev_id;
+
 	/*
 	 * irqs should be disabled here, but as the irq is shared they are only
 	 * guaranteed to be off if the timer irq is registered first.
@@ -102,15 +124,15 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
 	WARN_ON_ONCE(!irqs_disabled());
 
 	/* The PIT interrupt may be disabled, and is shared */
-	if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)
-			&& (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS)) {
+	if ((data->ced.mode == CLOCK_EVT_MODE_PERIODIC)
+			&& (at91_pit_read(data, AT91_PIT_SR) & AT91_PIT_PITS)) {
 		unsigned nr_ticks;
 
 		/* Get number of ticks performed before irq, and ack it */
-		nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+		nr_ticks = PIT_PICNT(at91_pit_read(data, AT91_PIT_PIVR));
 		do {
-			pit_cnt += pit_cycle;
-			pit_clkevt.event_handler(&pit_clkevt);
+			data->pit_cnt += data->pit_cycle;
+			data->ced.event_handler(&data->ced);
 			nr_ticks--;
 		} while (nr_ticks);
 
@@ -120,69 +142,192 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
-static struct irqaction at91sam926x_pit_irq = {
-	.name		= "at91_tick",
-	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= at91sam926x_pit_interrupt
-};
+static void at91_pit_stop(struct at91_pit_data *data)
+{
+	/* Disable timer and irqs */
+	at91_pit_write(data, AT91_PIT_MR, 0);
+}
 
-static void at91sam926x_pit_reset(void)
+static void at91_pit_reset(struct at91_pit_data *data)
 {
 	/* Disable timer and irqs */
-	at91_sys_write(AT91_PIT_MR, 0);
+	at91_pit_stop(data);
 
 	/* Clear any pending interrupts, wait for PIT to stop counting */
-	while (PIT_CPIV(at91_sys_read(AT91_PIT_PIVR)) != 0)
+	while (PIT_CPIV(at91_pit_read(data, AT91_PIT_PIVR)) != 0)
 		cpu_relax();
 
 	/* Start PIT but don't enable IRQ */
-	at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+	at91_pit_write(data, AT91_PIT_MR, (data->pit_cycle - 1) | AT91_PIT_PITEN);
 }
 
-/*
- * Set up both clocksource and clockevent support.
- */
-static void __init at91sam926x_pit_init(void)
+static int at91_pit_clocksource_enable(struct clocksource *cs)
+{
+	struct at91_pit_data *data = cs_to_at91_pit(cs);
+
+	at91_pit_reset(data);
+
+	return 0;
+}
+
+static void at91_pit_clocksource_resume(struct clocksource *cs)
+{
+	struct at91_pit_data *data = cs_to_at91_pit(cs);
+
+	at91_pit_reset(data);
+}
+
+static void at91_pit_clocksource_disable(struct clocksource *cs)
+{
+	struct at91_pit_data *data = cs_to_at91_pit(cs);
+
+	at91_pit_stop(data);
+}
+
+static void at91_pit_register_clockevent(struct at91_pit_data *data,
+					 unsigned long pit_rate)
+{
+	struct clock_event_device *ced = &data->ced;
+
+	memset(ced, 0, sizeof(*ced));
+
+	ced->name = "pit";
+	ced->features = CLOCK_EVT_FEAT_PERIODIC;
+	ced->shift = 32;
+	ced->rating = 100;
+	ced->set_mode = at91_pit_clock_event_mode;
+	ced->cpumask = cpumask_of(0);
+	ced->mult = div_sc(pit_rate, NSEC_PER_SEC, ced->shift);
+
+	dev_info(&data->pdev->dev, "used for clock events\n");
+
+	clockevents_register_device(ced);
+}
+
+static int at91_pit_register_clocksource(struct at91_pit_data *data,
+					 unsigned long pit_rate)
+{
+	struct clocksource *cs = &data->cs;
+	unsigned bits;
+
+	cs->name = "pit";
+	cs->rating = 175;
+	cs->shift = 20;
+	cs->read = at91_pit_clocksource_read;
+	cs->enable = at91_pit_clocksource_enable;
+	cs->disable = at91_pit_clocksource_disable;
+	cs->suspend = at91_pit_clocksource_disable;
+	cs->resume = at91_pit_clocksource_resume;
+	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	cs->mult = clocksource_hz2mult(pit_rate, cs->shift);
+	bits = 12 /* PICNT */ + ilog2(data->pit_cycle) /* PIV */;
+	cs->mask = CLOCKSOURCE_MASK(bits);
+
+	dev_info(&data->pdev->dev, "used as clock source\n");
+
+	clocksource_register_hz(cs, pit_rate);
+
+	return 0;
+}
+
+static int at91_pit_setup(struct at91_pit_data *data,
+			  struct platform_device *pdev)
 {
 	unsigned long	pit_rate;
-	unsigned	bits;
+	struct resource	*res;
+	int		irq;
+	int		ret = -ENXIO;
+
+	memset(data, 0, sizeof(struct at91_pit_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_pit_interrupt;
+	data->irqaction.dev_id = data;
+	data->irqaction.flags = IRQF_SHARED | IRQF_DISABLED |
+				IRQF_TIMER  | IRQF_IRQPOLL;
 
 	/*
 	 * Use our actual MCK to figure out how many MCK/16 ticks per
 	 * 1/HZ period (instead of a compile-time constant LATCH).
 	 */
 	pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16;
-	pit_cycle = (pit_rate + HZ/2) / HZ;
-	WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
+	data->pit_cycle = (pit_rate + HZ/2) / HZ;
+	WARN_ON(((data->pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
 
 	/* Initialize and enable the timer */
-	at91sam926x_pit_reset();
+	at91_pit_reset(data);
 
 	/*
 	 * Register clocksource.  The high order bits of PIV are unused,
 	 * so this isn't a 32-bit counter unless we get clockevent irqs.
 	 */
-	bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
-	pit_clk.mask = CLOCKSOURCE_MASK(bits);
-	clocksource_register_hz(&pit_clk, pit_rate);
+	at91_pit_register_clocksource(data, pit_rate);
 
 	/* Set up irq handler */
-	setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq);
+	setup_irq(irq, &data->irqaction);
 
 	/* Set up and register clockevents */
-	pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift);
-	pit_clkevt.cpumask = cpumask_of(0);
-	clockevents_register_device(&pit_clkevt);
+	at91_pit_register_clockevent(data, pit_rate);
+
+	return 0;
+
+err0:
+	return ret;
+}
+
+static int __devinit at91_pit_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct at91_pit_data *data;
+
+	if (!is_early_platform_device(pdev)) {
+		pr_info("at91_pit.%d: call via non early plaform\n", pdev->id);
+		return 0;
+	}
+
+	data = kmalloc(sizeof(struct at91_pit_data), GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	ret = at91_pit_setup(data, pdev);
+
+	if (ret)
+		kfree(data);
+
+	return ret;
 }
 
-static void at91sam926x_pit_suspend(void)
+static int __devexit at91_pit_remove(struct platform_device *pdev)
 {
-	/* Disable timer */
-	at91_sys_write(AT91_PIT_MR, 0);
+	return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
-struct sys_timer at91sam926x_timer = {
-	.init		= at91sam926x_pit_init,
-	.suspend	= at91sam926x_pit_suspend,
-	.resume		= at91sam926x_pit_reset,
+static struct platform_driver at91_pit_device_driver = {
+	.probe		= at91_pit_probe,
+	.remove		= __devexit_p(at91_pit_remove),
+	.driver		= {
+		.name	= "at91_pit",
+	}
 };
+
+early_platform_init("earlytimer", &at91_pit_device_driver);
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 0fee23f..077eecf 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -402,6 +402,11 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ0) */
 };
 
+struct at91_dev_resource at91sam9g45_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91sam9g45_soc = {
 	.name = "at91sam9g45",
 	.default_irq_priority = at91sam9g45_default_irq_priority,
@@ -410,4 +415,5 @@ struct at91_soc __initdata at91sam9g45_soc = {
 		.resource = at91sam9g45_pios,
 		.num_resources = ARRAY_SIZE(at91sam9g45_pios),
 	},
+	.pit = &at91sam9g45_pit,
 };
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index ec62ca01..7623617 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -368,6 +368,11 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
+struct at91_dev_resource at91sam9rl_pit __initdata = {
+	.mmio_base	= AT91_PIT,
+	.irq		= AT91_ID_SYS,
+};
+
 struct at91_soc __initdata at91sam9rl_soc = {
 	.name = "at91sam9rl",
 	.default_irq_priority = at91sam9rl_default_irq_priority,
@@ -376,4 +381,5 @@ struct at91_soc __initdata at91sam9rl_soc = {
 		.resource = at91sam9rl_pios,
 		.num_resources = ARRAY_SIZE(at91sam9rl_pios),
 	},
+	.pit = &at91sam9rl_pit,
 };
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 3103bb1..71304fe 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -219,7 +219,7 @@ static void __init afeb9260_board_init(void)
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
 	/* Maintainer: Sergey Lapin <slapin at ossfans.org> */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= afeb9260_map_io,
 	.init_irq	= afeb9260_init_irq,
 	.init_machine	= afeb9260_board_init,
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index 1d24493..61d11af 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -316,7 +316,7 @@ static void __init eb_board_init(void)
 MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
 	/* Maintainer: Atmel <costa.antonior at gmail.com> */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= eb_map_io,
 	.init_irq	= eb_init_irq,
 	.init_machine	= eb_board_init,
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index d3a65e2..5d65fe5 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -199,7 +199,7 @@ static void __init cam60_board_init(void)
 MACHINE_START(CAM60, "KwikByte CAM60")
 	/* Maintainer: KwikByte */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= cam60_map_io,
 	.init_irq	= cam60_init_irq,
 	.init_machine	= cam60_board_init,
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index 8f0a53e..939a2a6 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -397,7 +397,7 @@ static void __init cap9adk_board_init(void)
 MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
 	/* Maintainer: Stelian Pop <stelian.pop at leadtechdesign.com> */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= cap9adk_map_io,
 	.init_irq	= cap9adk_init_irq,
 	.init_machine	= cap9adk_board_init,
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 544995c..625f485 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -376,7 +376,7 @@ MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
 #endif
 	/* Maintainer: Eric Benard - EUKREA Electromatique */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= cpu9krea_map_io,
 	.init_irq	= cpu9krea_init_irq,
 	.init_machine	= cpu9krea_board_init,
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 15cf7ab..478ae2f 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -155,7 +155,7 @@ static void __init flexibity_board_init(void)
 MACHINE_START(FLEXIBITY, "Flexibity Connect")
 	/* Maintainer: Maxim Osipov */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= flexibity_map_io,
 	.init_irq	= flexibity_init_irq,
 	.init_machine	= flexibity_board_init,
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 53032d4..51de65f 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -267,7 +267,7 @@ static void __init foxg20_board_init(void)
 MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
 	/* Maintainer: Sergio Tanzilli */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= foxg20_map_io,
 	.init_irq	= foxg20_init_irq,
 	.init_machine	= foxg20_board_init,
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index 41f7164..8d40325 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -577,7 +577,7 @@ static void __init gsia18s_board_init(void)
 
 MACHINE_START(GSIA18S, "GS_IA18_S")
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= gsia18s_map_io,
 	.init_irq	= init_irq,
 	.init_machine	= gsia18s_board_init,
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 2d1dec2..b313b7e 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -388,7 +388,7 @@ static void __init neocore926_board_init(void)
 MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
 	/* Maintainer: ADENEO */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= neocore926_map_io,
 	.init_irq	= neocore926_init_irq,
 	.init_machine	= neocore926_board_init,
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index aa0a660..b577569 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -223,7 +223,7 @@ static void __init pcontrol_g20_board_init(void)
 MACHINE_START(PCONTROL_G20, "PControl G20")
 	/* Maintainer: pgsellmann at portner-elektronik.at */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= pcontrol_g20_map_io,
 	.init_irq	= init_irq,
 	.init_machine	= pcontrol_g20_board_init,
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index e26fa6e..b131aab 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -269,7 +269,7 @@ static void __init ek_board_init(void)
 MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
 	/* Maintainer: calao-systems */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index e4e19aa..2b569e6 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -213,7 +213,7 @@ static void __init ek_board_init(void)
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
 	/* Maintainer: Olimex */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 2307a1c..e27951f 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -354,7 +354,7 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index e1c4274..9160999 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -621,7 +621,7 @@ MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
 #endif
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 43c421d..1dfb4ad 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -452,7 +452,7 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 5a5df34..aff0782 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -404,7 +404,7 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= ek_map_io,
 	.init_irq	= ek_init_irq,
 	.init_machine	= ek_board_init,
@@ -413,7 +413,7 @@ MACHINE_END
 MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index fef316a..9aa68d7 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -422,7 +422,7 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 535c975..4020808 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -330,7 +330,7 @@ static void __init ek_board_init(void)
 MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
 	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index a5d5d89..b5a8bd8 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -179,7 +179,7 @@ static void __init snapper9260_board_init(void)
 
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= snapper9260_map_io,
 	.init_irq	= snapper9260_init_irq,
 	.init_machine	= snapper9260_board_init,
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 1b435c3..1c92df0 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -299,7 +299,7 @@ static void __init stamp9g20evb_board_init(void)
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
 	/* Maintainer: taskit GmbH */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= portuxg20_map_io,
 	.init_irq	= init_irq,
 	.init_machine	= portuxg20_board_init,
@@ -308,7 +308,7 @@ MACHINE_END
 MACHINE_START(STAMP9G20, "taskit Stamp9G20")
 	/* Maintainer: taskit GmbH */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= stamp9g20evb_map_io,
 	.init_irq	= init_irq,
 	.init_machine	= stamp9g20evb_board_init,
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
index a1cb555..349e31a 100644
--- a/arch/arm/mach-at91/board-usb-a926x.c
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -280,7 +280,7 @@ static void __init ek_board_init(void)
 MACHINE_START(USB_A9263, "CALAO USB_A9263")
 	/* Maintainer: calao-systems */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
+	.timer		= &at91_timer,
 	.map_io		= ek_map_io,
 	.init_irq	= ek_init_irq,
 	.init_machine	= ek_board_init,
@@ -289,7 +289,7 @@ MACHINE_END
 MACHINE_START(USB_A9260, "CALAO USB_A9260")
 	/* Maintainer: calao-systems */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_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/devices.c b/arch/arm/mach-at91/devices.c
index 03ded48..b11154d 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -8,8 +8,8 @@
  *
  */
 
-#include <linux/platform_device.h>
 
-#include "devices.h"
+
+#include "soc.h"
 
 
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index b2c7c3a..1cfe696 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -23,7 +23,7 @@ extern void __init at91_aic_init(unsigned int priority[]);
  /* Timer */
 struct sys_timer;
 extern struct sys_timer at91rm9200_timer;
-extern struct sys_timer at91sam926x_timer;
+extern struct sys_timer at91_timer;
 extern struct sys_timer at91x40_timer;
 
  /* Clocks */
diff --git a/arch/arm/mach-at91/include/mach/at91_pit.h b/arch/arm/mach-at91/include/mach/at91_pit.h
index 974d0bd..380ef93 100644
--- a/arch/arm/mach-at91/include/mach/at91_pit.h
+++ b/arch/arm/mach-at91/include/mach/at91_pit.h
@@ -16,16 +16,16 @@
 #ifndef AT91_PIT_H
 #define AT91_PIT_H
 
-#define AT91_PIT_MR		(AT91_PIT + 0x00)	/* Mode Register */
+#define AT91_PIT_MR		(0x00)			/* Mode Register */
 #define		AT91_PIT_PITIEN		(1 << 25)		/* Timer Interrupt Enable */
 #define		AT91_PIT_PITEN		(1 << 24)		/* Timer Enabled */
 #define		AT91_PIT_PIV		(0xfffff)		/* Periodic Interval Value */
 
-#define AT91_PIT_SR		(AT91_PIT + 0x04)	/* Status Register */
+#define AT91_PIT_SR		(0x04)			/* Status Register */
 #define		AT91_PIT_PITS		(1 << 0)		/* Timer Status */
 
-#define AT91_PIT_PIVR		(AT91_PIT + 0x08)	/* Periodic Interval Value Register */
-#define AT91_PIT_PIIR		(AT91_PIT + 0x0c)	/* Periodic Interval Image Register */
+#define AT91_PIT_PIVR		(0x08)			/* Periodic Interval Value Register */
+#define AT91_PIT_PIIR		(0x0c)			/* Periodic Interval Image Register */
 #define		AT91_PIT_PICNT		(0xfff << 20)		/* Interval Counter */
 #define		AT91_PIT_CPIV		(0xfffff)		/* Inverval Value */
 
diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c
index 0e8604c..7b44be2 100644
--- a/arch/arm/mach-at91/soc.c
+++ b/arch/arm/mach-at91/soc.c
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
+#include <asm/mach/time.h>
 
 #include <mach/hardware.h>
 #include <mach/cpu.h>
@@ -212,3 +213,44 @@ static void __init at91_add_gpio(void)
 	early_platform_driver_register_all("early_at91_gpio");
 	early_platform_driver_probe("early_at91_gpio", nb , 0);
 }
+
+/*
+ * Set up both clocksource and clockevent support.
+ */
+static struct resource pit_resources[] = {
+	[0] = RES_MEM(SZ_16),
+	[1] = RES_IRQ(),
+};
+
+static struct platform_device at91_pit_device = {
+	.name		= "at91_pit",
+	.id		= 0,
+	.resource	= pit_resources,
+	.num_resources	= ARRAY_SIZE(pit_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);
+
+	if (current_soc.pit) {
+		r = pit_resources;
+		res = current_soc.pit;
+		pdev = &at91_pit_device;
+	}
+
+	set_resource_mem(&r[0], res->mmio_base);
+	set_resource_irq(&r[1], res->irq);
+
+	early_platform_add_devices(&pdev, 1);
+	early_platform_driver_register_all("earlytimer");
+	early_platform_driver_probe("earlytimer", 1 , 0);
+}
+
+struct sys_timer at91_timer = {
+	.init		= at91_timer_init,
+};
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index bf90d48..8df07a2 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -13,6 +13,7 @@ struct at91_soc {
 	unsigned int *default_irq_priority;
 
 	struct at91_dev_resource_array gpio;
+	struct at91_dev_resource *pit;
 
 	void (*init)(unsigned long main_clock);
 };
-- 
1.7.4.1




More information about the linux-arm-kernel mailing list