ARM: at91: PIT: Move the driver to drivers/clocksource
authorMaxime Ripard <maxime.ripard@free-electrons.com>
Tue, 2 Sep 2014 16:12:35 +0000 (18:12 +0200)
committerNicolas Ferre <nicolas.ferre@atmel.com>
Mon, 15 Sep 2014 15:55:48 +0000 (17:55 +0200)
Now that we don't depend on anyting in the mach-at91 directory, we can just
move the driver to where it belongs.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Conflicts:
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile

arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91sam926x_time.c [deleted file]
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/timer-atmel-pit.c [new file with mode: 0644]

index c3f9ebc5f9f52fd9956682535a96a11c5404488f..474c855fa83c25a65593764ff1d4986864df3728 100644 (file)
@@ -33,16 +33,11 @@ config OLD_IRQ_AT91
        select MULTI_IRQ_HANDLER
        select SPARSE_IRQ
 
-config AT91_SAM9_TIME
-       select CLKSRC_OF if OF
-       bool
-
 config HAVE_AT91_SMD
        bool
 
 config SOC_AT91SAM9
        bool
-       select AT91_SAM9_TIME
        select ATMEL_AIC_IRQ if !OLD_IRQ_AT91
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
@@ -51,7 +46,6 @@ config SOC_AT91SAM9
 
 config SOC_SAMA5
        bool
-       select AT91_SAM9_TIME
        select ATMEL_AIC5_IRQ
        select CPU_V7
        select GENERIC_CLOCKEVENTS
index 306c82b3d45c038ca50036227ba0d581e9b7df8c..61d04f9314e744ac587d679821d4aaf7638c8188 100644 (file)
@@ -9,7 +9,6 @@ obj-            :=
 
 obj-$(CONFIG_OLD_IRQ_AT91)     += irq.o
 obj-$(CONFIG_OLD_CLK_AT91)     += clock.o
-obj-$(CONFIG_AT91_SAM9_TIME)   += at91sam926x_time.o
 obj-$(CONFIG_SOC_AT91SAM9)     += sam9_smc.o
 
 # CPU-specific support
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
deleted file mode 100644 (file)
index d528909..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
- *
- * 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.
- *
- * 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.
- */
-
-#define pr_fmt(fmt)    "AT91: PIT: " fmt
-
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/slab.h>
-
-#define AT91_PIT_MR            0x00                    /* Mode Register */
-#define AT91_PIT_PITIEN                        BIT(25)                 /* Timer Interrupt Enable */
-#define AT91_PIT_PITEN                 BIT(24)                 /* Timer Enabled */
-#define AT91_PIT_PIV                   GENMASK(19, 0)          /* Periodic Interval Value */
-
-#define AT91_PIT_SR            0x04                    /* Status Register */
-#define AT91_PIT_PITS                  BIT(0)                  /* Timer Status */
-
-#define AT91_PIT_PIVR          0x08                    /* Periodic Interval Value Register */
-#define AT91_PIT_PIIR          0x0c                    /* Periodic Interval Image Register */
-#define AT91_PIT_PICNT                 GENMASK(31, 20)         /* Interval Counter */
-#define AT91_PIT_CPIV                  GENMASK(19, 0)          /* Inverval Value */
-
-#define PIT_CPIV(x)    ((x) & AT91_PIT_CPIV)
-#define PIT_PICNT(x)   (((x) & AT91_PIT_PICNT) >> 20)
-
-struct pit_data {
-       struct clock_event_device       clkevt;
-       struct clocksource              clksrc;
-
-       void __iomem    *base;
-       u32             cycle;
-       u32             cnt;
-       unsigned int    irq;
-       struct clk      *mck;
-};
-
-static inline struct pit_data *clksrc_to_pit_data(struct clocksource *clksrc)
-{
-       return container_of(clksrc, struct pit_data, clksrc);
-}
-
-static inline struct pit_data *clkevt_to_pit_data(struct clock_event_device *clkevt)
-{
-       return container_of(clkevt, struct pit_data, clkevt);
-}
-
-static inline unsigned int pit_read(void __iomem *base, unsigned int reg_offset)
-{
-       return __raw_readl(base + reg_offset);
-}
-
-static inline void pit_write(void __iomem *base, unsigned int reg_offset, unsigned long value)
-{
-       __raw_writel(value, base + reg_offset);
-}
-
-/*
- * 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)
-{
-       struct pit_data *data = clksrc_to_pit_data(cs);
-       unsigned long flags;
-       u32 elapsed;
-       u32 t;
-
-       raw_local_irq_save(flags);
-       elapsed = data->cnt;
-       t = pit_read(data->base, AT91_PIT_PIIR);
-       raw_local_irq_restore(flags);
-
-       elapsed += PIT_PICNT(t) * data->cycle;
-       elapsed += PIT_CPIV(t);
-       return elapsed;
-}
-
-/*
- * 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)
-{
-       struct pit_data *data = clkevt_to_pit_data(dev);
-
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               /* update clocksource counter */
-               data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
-               pit_write(data->base, AT91_PIT_MR,
-                         (data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               BUG();
-               /* FALLTHROUGH */
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_UNUSED:
-               /* disable irq, leaving the clocksource active */
-               pit_write(data->base, AT91_PIT_MR,
-                         (data->cycle - 1) | AT91_PIT_PITEN);
-               break;
-       case CLOCK_EVT_MODE_RESUME:
-               break;
-       }
-}
-
-static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
-{
-       struct pit_data *data = clkevt_to_pit_data(cedev);
-
-       /* Disable timer */
-       pit_write(data->base, AT91_PIT_MR, 0);
-}
-
-static void at91sam926x_pit_reset(struct pit_data *data)
-{
-       /* Disable timer and irqs */
-       pit_write(data->base, AT91_PIT_MR, 0);
-
-       /* Clear any pending interrupts, wait for PIT to stop counting */
-       while (PIT_CPIV(pit_read(data->base, AT91_PIT_PIVR)) != 0)
-               cpu_relax();
-
-       /* Start PIT but don't enable IRQ */
-       pit_write(data->base, AT91_PIT_MR,
-                 (data->cycle - 1) | AT91_PIT_PITEN);
-}
-
-static void at91sam926x_pit_resume(struct clock_event_device *cedev)
-{
-       struct pit_data *data = clkevt_to_pit_data(cedev);
-
-       at91sam926x_pit_reset(data);
-}
-
-/*
- * IRQ handler for the timer.
- */
-static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
-{
-       struct pit_data *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.
-        */
-       WARN_ON_ONCE(!irqs_disabled());
-
-       /* The PIT interrupt may be disabled, and is shared */
-       if ((data->clkevt.mode == CLOCK_EVT_MODE_PERIODIC) &&
-           (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) {
-               unsigned nr_ticks;
-
-               /* Get number of ticks performed before irq, and ack it */
-               nr_ticks = PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
-               do {
-                       data->cnt += data->cycle;
-                       data->clkevt.event_handler(&data->clkevt);
-                       nr_ticks--;
-               } while (nr_ticks);
-
-               return IRQ_HANDLED;
-       }
-
-       return IRQ_NONE;
-}
-
-/*
- * Set up both clocksource and clockevent support.
- */
-static void __init at91sam926x_pit_common_init(struct pit_data *data)
-{
-       unsigned long   pit_rate;
-       unsigned        bits;
-       int             ret;
-
-       /*
-        * 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(data->mck) / 16;
-       data->cycle = DIV_ROUND_CLOSEST(pit_rate, HZ);
-       WARN_ON(((data->cycle - 1) & ~AT91_PIT_PIV) != 0);
-
-       /* Initialize and enable the timer */
-       at91sam926x_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(data->cycle) /* PIV */;
-       data->clksrc.mask = CLOCKSOURCE_MASK(bits);
-       data->clksrc.name = "pit";
-       data->clksrc.rating = 175;
-       data->clksrc.read = read_pit_clk,
-       data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS,
-       clocksource_register_hz(&data->clksrc, pit_rate);
-
-       /* Set up irq handler */
-       ret = request_irq(data->irq, at91sam926x_pit_interrupt,
-                         IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
-                         "at91_tick", data);
-       if (ret)
-               panic(pr_fmt("Unable to setup IRQ\n"));
-
-       /* Set up and register clockevents */
-       data->clkevt.name = "pit";
-       data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
-       data->clkevt.shift = 32;
-       data->clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, data->clkevt.shift);
-       data->clkevt.rating = 100;
-       data->clkevt.cpumask = cpumask_of(0);
-
-       data->clkevt.set_mode = pit_clkevt_mode;
-       data->clkevt.resume = at91sam926x_pit_resume;
-       data->clkevt.suspend = at91sam926x_pit_suspend;
-       clockevents_register_device(&data->clkevt);
-}
-
-static void __init at91sam926x_pit_dt_init(struct device_node *node)
-{
-       struct pit_data *data;
-
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               panic(pr_fmt("Unable to allocate memory\n"));
-
-       data->base = of_iomap(node, 0);
-       if (!data->base)
-               panic(pr_fmt("Could not map PIT address\n"));
-
-       data->mck = of_clk_get(node, 0);
-       if (IS_ERR(data->mck))
-               /* Fallback on clkdev for !CCF-based boards */
-               data->mck = clk_get(NULL, "mck");
-
-       if (IS_ERR(data->mck))
-               panic(pr_fmt("Unable to get mck clk\n"));
-
-       /* Get the interrupts property */
-       data->irq = irq_of_parse_and_map(node, 0);
-       if (!data->irq)
-               panic(pr_fmt("Unable to get IRQ from DT\n"));
-
-       at91sam926x_pit_common_init(data);
-}
-CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
-                      at91sam926x_pit_dt_init);
-
-static void __iomem *pit_base_addr;
-
-void __init at91sam926x_pit_init(int irq)
-{
-       struct pit_data *data;
-
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               panic(pr_fmt("Unable to allocate memory\n"));
-
-       data->base = pit_base_addr;
-
-       data->mck = clk_get(NULL, "mck");
-       if (IS_ERR(data->mck))
-               panic(pr_fmt("Unable to get mck clk\n"));
-
-       data->irq = irq;
-
-       at91sam926x_pit_common_init(data);
-}
-
-void __init at91sam926x_ioremap_pit(u32 addr)
-{
-       if (of_have_populated_dt())
-               return;
-
-       pit_base_addr = ioremap(addr, 16);
-
-       if (!pit_base_addr)
-               panic(pr_fmt("Impossible to ioremap PIT\n"));
-}
index cfd6519df6615fc1a9268fcaf092859adf4323c9..82a2ebe41e27706213a1670a2f3cdee3488b0a94 100644 (file)
@@ -120,6 +120,10 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
        help
         Use ARM global timer clock source as sched_clock
 
+config ATMEL_PIT
+       select CLKSRC_OF if OF
+       def_bool SOC_AT91SAM9 || SOC_SAMA5
+
 config CLKSRC_METAG_GENERIC
        def_bool y if METAG
        help
index 7fd9fd1dff42f29aebec34bfa684bc950cb97ab8..e566f6c7ded4925c2904132f376f5380ce4bb6d1 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_CLKSRC_OF)        += clksrc-of.o
+obj-$(CONFIG_ATMEL_PIT)                += timer-atmel-pit.o
 obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
 obj-$(CONFIG_X86_PM_TIMER)     += acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)   += scx200_hrt.o
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
new file mode 100644 (file)
index 0000000..d528909
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt)    "AT91: PIT: " fmt
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#define AT91_PIT_MR            0x00                    /* Mode Register */
+#define AT91_PIT_PITIEN                        BIT(25)                 /* Timer Interrupt Enable */
+#define AT91_PIT_PITEN                 BIT(24)                 /* Timer Enabled */
+#define AT91_PIT_PIV                   GENMASK(19, 0)          /* Periodic Interval Value */
+
+#define AT91_PIT_SR            0x04                    /* Status Register */
+#define AT91_PIT_PITS                  BIT(0)                  /* Timer Status */
+
+#define AT91_PIT_PIVR          0x08                    /* Periodic Interval Value Register */
+#define AT91_PIT_PIIR          0x0c                    /* Periodic Interval Image Register */
+#define AT91_PIT_PICNT                 GENMASK(31, 20)         /* Interval Counter */
+#define AT91_PIT_CPIV                  GENMASK(19, 0)          /* Inverval Value */
+
+#define PIT_CPIV(x)    ((x) & AT91_PIT_CPIV)
+#define PIT_PICNT(x)   (((x) & AT91_PIT_PICNT) >> 20)
+
+struct pit_data {
+       struct clock_event_device       clkevt;
+       struct clocksource              clksrc;
+
+       void __iomem    *base;
+       u32             cycle;
+       u32             cnt;
+       unsigned int    irq;
+       struct clk      *mck;
+};
+
+static inline struct pit_data *clksrc_to_pit_data(struct clocksource *clksrc)
+{
+       return container_of(clksrc, struct pit_data, clksrc);
+}
+
+static inline struct pit_data *clkevt_to_pit_data(struct clock_event_device *clkevt)
+{
+       return container_of(clkevt, struct pit_data, clkevt);
+}
+
+static inline unsigned int pit_read(void __iomem *base, unsigned int reg_offset)
+{
+       return __raw_readl(base + reg_offset);
+}
+
+static inline void pit_write(void __iomem *base, unsigned int reg_offset, unsigned long value)
+{
+       __raw_writel(value, base + reg_offset);
+}
+
+/*
+ * 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)
+{
+       struct pit_data *data = clksrc_to_pit_data(cs);
+       unsigned long flags;
+       u32 elapsed;
+       u32 t;
+
+       raw_local_irq_save(flags);
+       elapsed = data->cnt;
+       t = pit_read(data->base, AT91_PIT_PIIR);
+       raw_local_irq_restore(flags);
+
+       elapsed += PIT_PICNT(t) * data->cycle;
+       elapsed += PIT_CPIV(t);
+       return elapsed;
+}
+
+/*
+ * 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)
+{
+       struct pit_data *data = clkevt_to_pit_data(dev);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               /* update clocksource counter */
+               data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
+               pit_write(data->base, AT91_PIT_MR,
+                         (data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               BUG();
+               /* FALLTHROUGH */
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+               /* disable irq, leaving the clocksource active */
+               pit_write(data->base, AT91_PIT_MR,
+                         (data->cycle - 1) | AT91_PIT_PITEN);
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               break;
+       }
+}
+
+static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
+{
+       struct pit_data *data = clkevt_to_pit_data(cedev);
+
+       /* Disable timer */
+       pit_write(data->base, AT91_PIT_MR, 0);
+}
+
+static void at91sam926x_pit_reset(struct pit_data *data)
+{
+       /* Disable timer and irqs */
+       pit_write(data->base, AT91_PIT_MR, 0);
+
+       /* Clear any pending interrupts, wait for PIT to stop counting */
+       while (PIT_CPIV(pit_read(data->base, AT91_PIT_PIVR)) != 0)
+               cpu_relax();
+
+       /* Start PIT but don't enable IRQ */
+       pit_write(data->base, AT91_PIT_MR,
+                 (data->cycle - 1) | AT91_PIT_PITEN);
+}
+
+static void at91sam926x_pit_resume(struct clock_event_device *cedev)
+{
+       struct pit_data *data = clkevt_to_pit_data(cedev);
+
+       at91sam926x_pit_reset(data);
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
+{
+       struct pit_data *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.
+        */
+       WARN_ON_ONCE(!irqs_disabled());
+
+       /* The PIT interrupt may be disabled, and is shared */
+       if ((data->clkevt.mode == CLOCK_EVT_MODE_PERIODIC) &&
+           (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) {
+               unsigned nr_ticks;
+
+               /* Get number of ticks performed before irq, and ack it */
+               nr_ticks = PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
+               do {
+                       data->cnt += data->cycle;
+                       data->clkevt.event_handler(&data->clkevt);
+                       nr_ticks--;
+               } while (nr_ticks);
+
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+/*
+ * Set up both clocksource and clockevent support.
+ */
+static void __init at91sam926x_pit_common_init(struct pit_data *data)
+{
+       unsigned long   pit_rate;
+       unsigned        bits;
+       int             ret;
+
+       /*
+        * 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(data->mck) / 16;
+       data->cycle = DIV_ROUND_CLOSEST(pit_rate, HZ);
+       WARN_ON(((data->cycle - 1) & ~AT91_PIT_PIV) != 0);
+
+       /* Initialize and enable the timer */
+       at91sam926x_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(data->cycle) /* PIV */;
+       data->clksrc.mask = CLOCKSOURCE_MASK(bits);
+       data->clksrc.name = "pit";
+       data->clksrc.rating = 175;
+       data->clksrc.read = read_pit_clk,
+       data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+       clocksource_register_hz(&data->clksrc, pit_rate);
+
+       /* Set up irq handler */
+       ret = request_irq(data->irq, at91sam926x_pit_interrupt,
+                         IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
+                         "at91_tick", data);
+       if (ret)
+               panic(pr_fmt("Unable to setup IRQ\n"));
+
+       /* Set up and register clockevents */
+       data->clkevt.name = "pit";
+       data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+       data->clkevt.shift = 32;
+       data->clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, data->clkevt.shift);
+       data->clkevt.rating = 100;
+       data->clkevt.cpumask = cpumask_of(0);
+
+       data->clkevt.set_mode = pit_clkevt_mode;
+       data->clkevt.resume = at91sam926x_pit_resume;
+       data->clkevt.suspend = at91sam926x_pit_suspend;
+       clockevents_register_device(&data->clkevt);
+}
+
+static void __init at91sam926x_pit_dt_init(struct device_node *node)
+{
+       struct pit_data *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               panic(pr_fmt("Unable to allocate memory\n"));
+
+       data->base = of_iomap(node, 0);
+       if (!data->base)
+               panic(pr_fmt("Could not map PIT address\n"));
+
+       data->mck = of_clk_get(node, 0);
+       if (IS_ERR(data->mck))
+               /* Fallback on clkdev for !CCF-based boards */
+               data->mck = clk_get(NULL, "mck");
+
+       if (IS_ERR(data->mck))
+               panic(pr_fmt("Unable to get mck clk\n"));
+
+       /* Get the interrupts property */
+       data->irq = irq_of_parse_and_map(node, 0);
+       if (!data->irq)
+               panic(pr_fmt("Unable to get IRQ from DT\n"));
+
+       at91sam926x_pit_common_init(data);
+}
+CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
+                      at91sam926x_pit_dt_init);
+
+static void __iomem *pit_base_addr;
+
+void __init at91sam926x_pit_init(int irq)
+{
+       struct pit_data *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               panic(pr_fmt("Unable to allocate memory\n"));
+
+       data->base = pit_base_addr;
+
+       data->mck = clk_get(NULL, "mck");
+       if (IS_ERR(data->mck))
+               panic(pr_fmt("Unable to get mck clk\n"));
+
+       data->irq = irq;
+
+       at91sam926x_pit_common_init(data);
+}
+
+void __init at91sam926x_ioremap_pit(u32 addr)
+{
+       if (of_have_populated_dt())
+               return;
+
+       pit_base_addr = ioremap(addr, 16);
+
+       if (!pit_base_addr)
+               panic(pr_fmt("Impossible to ioremap PIT\n"));
+}