summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2017-03-08 14:09:09 -0800
committerSascha Hauer <s.hauer@pengutronix.de>2017-03-09 11:51:28 +0100
commita76714f7f9c6f1e3f1ebafc4fc2e197181ac9e8c (patch)
tree22211660a21c58bd450610360bd2dd2391f53962 /drivers/clocksource
parentd6200fe41500c9b06e12d43aaddd060eee8e1b8d (diff)
downloadbarebox-a76714f7f9c6f1e3f1ebafc4fc2e197181ac9e8c.tar.gz
barebox-a76714f7f9c6f1e3f1ebafc4fc2e197181ac9e8c.tar.xz
clocksource: at91: Move to 'drivers/clocksource'
Move PIT driver code to 'drivers/clocsource' and accomodate it by adjusting Kconfig variables. Rename the file to 'timer-atmel-pit.c' to re-align the driver with code in Linux kernel. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Kconfig4
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/timer-atmel-pit.c114
3 files changed, 119 insertions, 0 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index f1ab554f96..f3c3255ffc 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -53,3 +53,7 @@ config CLOCKSOURCE_UEMD
config CLOCKSOURCE_ROCKCHIP
bool
depends on ARCH_ROCKCHIP
+
+config CLOCKSOURCE_ATMEL_PIT
+ bool
+ depends on SOC_AT91SAM9 || SOC_SAMA5
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 39982ffb28..0564d8f5a9 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
obj-$(CONFIG_CLOCKSOURCE_UEMD) += uemd.o
obj-$(CONFIG_CLOCKSOURCE_ROCKCHIP)+= rk_timer.o
+obj-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += timer-atmel-pit.o
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
new file mode 100644
index 0000000000..cc7ad2f39a
--- /dev/null
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -0,0 +1,114 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <mach/hardware.h>
+#include <mach/at91_pit.h>
+#include <mach/io.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
+#define pit_write(reg, val) __raw_writel(val, pit_base + reg)
+#define pit_read(reg) __raw_readl(pit_base + reg)
+
+static __iomem void *pit_base;
+
+uint64_t at91sam9_clocksource_read(void)
+{
+ return pit_read(AT91_PIT_PIIR);
+}
+
+static struct clocksource cs = {
+ .read = at91sam9_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 10,
+};
+
+static void at91_pit_stop(void)
+{
+ /* Disable timer and irqs */
+ pit_write(AT91_PIT_MR, 0);
+
+ /* Clear any pending interrupts, wait for PIT to stop counting */
+ while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0);
+}
+
+static void at91sam926x_pit_reset(void)
+{
+ at91_pit_stop();
+
+ /* Start PIT but don't enable IRQ */
+ pit_write(AT91_PIT_MR, 0xfffff | AT91_PIT_PITEN);
+}
+
+static int at91_pit_probe(struct device_d *dev)
+{
+ struct clk *clk;
+ u32 pit_rate;
+ int ret;
+
+ clk = clk_get(dev, NULL);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(dev, "clock not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(clk);
+ if (ret < 0) {
+ dev_err(dev, "clock failed to enable: %d\n", ret);
+ clk_put(clk);
+ return ret;
+ }
+
+ pit_base = dev_request_mem_region_err_null(dev, 0);
+ if (!pit_base)
+ return -ENOENT;
+
+ pit_rate = clk_get_rate(clk) / 16;
+
+ at91sam926x_pit_reset();
+
+ cs.mult = clocksource_hz2mult(pit_rate, cs.shift);
+
+ return init_clock(&cs);
+}
+
+static struct driver_d at91_pit_driver = {
+ .name = "at91-pit",
+ .probe = at91_pit_probe,
+};
+
+static int at91_pit_init(void)
+{
+ return platform_driver_register(&at91_pit_driver);
+}
+postcore_initcall(at91_pit_init);