[PATCH 4/4] ARM: sa1100: switch to COMMON_CLK framework
Dmitry Eremin-Solenikov
dmitry_eremin at mentor.com
Fri Nov 1 06:52:11 EDT 2013
Implement common clock framework support for SA-1100.
Signed-off-by: Dmitry Eremin-Solenikov <dmitry_eremin at mentor.com>
---
arch/arm/Kconfig | 2 +-
arch/arm/mach-sa1100/clock.c | 100 ----------------------------------
arch/arm/mach-sa1100/generic.c | 2 +
drivers/clk/Makefile | 1 +
drivers/clk/clk-sa1100.c | 121 +++++++++++++++++++++++++++++++++++++++++
include/linux/clk/sa1100.h | 14 +++++
6 files changed, 139 insertions(+), 101 deletions(-)
delete mode 100644 arch/arm/mach-sa1100/clock.c
create mode 100644 drivers/clk/clk-sa1100.c
create mode 100644 include/linux/clk/sa1100.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5c86d8a..b28e518 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -686,8 +686,8 @@ config ARCH_SA1100
select ARCH_MTD_XIP
select ARCH_REQUIRE_GPIOLIB
select ARCH_SPARSEMEM_ENABLE
- select CLKDEV_LOOKUP
select CLKSRC_MMIO
+ select COMMON_CLK
select CPU_FREQ
select CPU_SA1100
select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
deleted file mode 100644
index 172ebd0..0000000
--- a/arch/arm/mach-sa1100/clock.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/clock.c
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-
-#include <mach/hardware.h>
-
-struct clkops {
- void (*enable)(struct clk *);
- void (*disable)(struct clk *);
-};
-
-struct clk {
- const struct clkops *ops;
- unsigned int enabled;
-};
-
-#define DEFINE_CLK(_name, _ops) \
-struct clk clk_##_name = { \
- .ops = _ops, \
- }
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void clk_gpio27_enable(struct clk *clk)
-{
- /*
- * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
- * (SA-1110 Developer's Manual, section 9.1.2.1)
- */
- GAFR |= GPIO_32_768kHz;
- GPDR |= GPIO_32_768kHz;
- TUCR = TUCR_3_6864MHz;
-}
-
-static void clk_gpio27_disable(struct clk *clk)
-{
- TUCR = 0;
- GPDR &= ~GPIO_32_768kHz;
- GAFR &= ~GPIO_32_768kHz;
-}
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
-
- if (clk) {
- spin_lock_irqsave(&clocks_lock, flags);
- if (clk->enabled++ == 0)
- clk->ops->enable(clk);
- spin_unlock_irqrestore(&clocks_lock, flags);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- if (clk) {
- WARN_ON(clk->enabled == 0);
- spin_lock_irqsave(&clocks_lock, flags);
- if (--clk->enabled == 0)
- clk->ops->disable(clk);
- spin_unlock_irqrestore(&clocks_lock, flags);
- }
-}
-EXPORT_SYMBOL(clk_disable);
-
-const struct clkops clk_gpio27_ops = {
- .enable = clk_gpio27_enable,
- .disable = clk_gpio27_disable,
-};
-
-static DEFINE_CLK(gpio27, &clk_gpio27_ops);
-
-static struct clk_lookup sa11xx_clkregs[] = {
- CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27),
- CLKDEV_INIT("sa1100-rtc", NULL, NULL),
-};
-
-static int __init sa11xx_clk_init(void)
-{
- clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
- return 0;
-}
-core_initcall(sa11xx_clk_init);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index d4ea142..f35dd06 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -20,6 +20,7 @@
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
+#include <linux/clk/sa1100.h>
#include <video/sa1100fb.h>
@@ -312,6 +313,7 @@ static struct platform_device *sa11x0_devices[] __initdata = {
static int __init sa1100_init(void)
{
pm_power_off = sa1100_power_off;
+ sa1100_clocks_init();
return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
}
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index fe3121b..0d46402 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
endif
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
+obj-$(CONFIG_ARCH_SA1100) += clk-sa1100.o
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
diff --git a/drivers/clk/clk-sa1100.c b/drivers/clk/clk-sa1100.c
new file mode 100644
index 0000000..b79d0f4
--- /dev/null
+++ b/drivers/clk/clk-sa1100.c
@@ -0,0 +1,121 @@
+/*
+ * 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 <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+
+enum {
+ osc32k768, osc3M6864,
+ gpio27_3M6864,
+ clk_max,
+};
+
+static struct clk *clks[clk_max];
+
+/*
+ * In reality it is a switch between 32k768 and 3M6864, driven on GPIO27,
+ * if it is enabled by GPIO Alternate function.
+ * However nobody uses 32k768 output (as it seems), so there is no point
+ * implementing it as a switch.
+ */
+static int gpio27_enabled;
+static int clk_gpio27_enable(struct clk_hw *hw)
+{
+ /*
+ * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
+ * (SA-1110 Developer's Manual, section 9.1.2.1)
+ */
+ GAFR |= GPIO_32_768kHz;
+ GPDR |= GPIO_32_768kHz;
+ TUCR = TUCR_3_6864MHz;
+
+ gpio27_enabled = 1;
+ return 0;
+}
+
+static void clk_gpio27_disable(struct clk_hw *hw)
+{
+ gpio27_enabled = 0;
+ TUCR = 0;
+ GPDR &= ~GPIO_32_768kHz;
+ GAFR &= ~GPIO_32_768kHz;
+}
+
+static int clk_gpio27_is_enabled(struct clk_hw *hw)
+{
+ return gpio27_enabled;
+}
+
+static const struct clk_ops clk_gpio27_ops = {
+ .enable = clk_gpio27_enable,
+ .disable = clk_gpio27_disable,
+ .is_enabled = clk_gpio27_is_enabled,
+};
+
+static struct clk *clk_register_gpio27(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags)
+{
+ struct clk_hw *gpio27;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ /* allocate the gpio27 */
+ gpio27 = kzalloc(sizeof(struct clk_hw), GFP_KERNEL);
+ if (!gpio27) {
+ pr_err("%s: could not allocate gpio27d clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = name;
+ init.ops = &clk_gpio27_ops;
+ init.flags = flags | CLK_IS_BASIC;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
+ /* struct clk_gpio27 assignments */
+ gpio27->init = &init;
+
+ clk = clk_register(dev, gpio27);
+
+ if (IS_ERR(clk))
+ kfree(gpio27);
+
+ return clk;
+}
+
+/* Fixed clocks on sa1100 */
+int __init sa1100_clocks_init(void)
+{
+ int i;
+
+ clks[osc32k768] = clk_register_fixed_rate(NULL, "osc32k768", NULL,
+ CLK_IS_ROOT, 32768);
+ clks[osc3M6864] = clk_register_fixed_rate(NULL, "osc3M6864", NULL,
+ CLK_IS_ROOT, 3686400);
+ clks[gpio27_3M6864] = clk_register_gpio27(NULL, "gpio27_3M6864",
+ "osc3M6864", 0);
+
+ clk_register_clkdev(clks[gpio27_3M6864], NULL, "sa1111.0");
+ clk_register_clkdev(clks[osc32k768], NULL, "sa1100-rtc");
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ if (IS_ERR(clks[i])) {
+ pr_err("SA1100 clk %d: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+ return PTR_ERR(clks[i]);
+ }
+
+ return 0;
+}
diff --git a/include/linux/clk/sa1100.h b/include/linux/clk/sa1100.h
new file mode 100644
index 0000000..497de03
--- /dev/null
+++ b/include/linux/clk/sa1100.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Dmitry Eremin-Solenikov
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_CLK_SA1100_H
+#define __LINUX_CLK_SA1100_H
+
+int sa1100_clocks_init(void);
+
+#endif
--
1.8.4.rc3
More information about the linux-arm-kernel
mailing list