clk: add MOXA ART SoCs clock driver
authorJonas Jensen <jonas.jensen@gmail.com>
Tue, 28 Jan 2014 11:09:11 +0000 (12:09 +0100)
committerMike Turquette <mturquette@linaro.org>
Wed, 19 Mar 2014 00:13:14 +0000 (17:13 -0700)
MOXA ART SoCs allow to determine PLL output and APB frequencies
by reading registers holding multiplier and divisor information.

Add a clock driver for this SoC.

Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt [new file with mode: 0644]
drivers/clk/Makefile
drivers/clk/clk-moxart.c [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt
new file mode 100644 (file)
index 0000000..fedea84
--- /dev/null
@@ -0,0 +1,48 @@
+Device Tree Clock bindings for arch-moxart
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+MOXA ART SoCs allow to determine PLL output and APB frequencies
+by reading registers holding multiplier and divisor information.
+
+
+PLL:
+
+Required properties:
+- compatible : Must be "moxa,moxart-pll-clock"
+- #clock-cells : Should be 0
+- reg : Should contain registers location and length
+- clocks : Should contain phandle + clock-specifier for the parent clock
+
+Optional properties:
+- clock-output-names : Should contain clock name
+
+
+APB:
+
+Required properties:
+- compatible : Must be "moxa,moxart-apb-clock"
+- #clock-cells : Should be 0
+- reg : Should contain registers location and length
+- clocks : Should contain phandle + clock-specifier for the parent clock
+
+Optional properties:
+- clock-output-names : Should contain clock name
+
+
+For example:
+
+       clk_pll: clk_pll@98100000 {
+               compatible = "moxa,moxart-pll-clock";
+               #clock-cells = <0>;
+               reg = <0x98100000 0x34>;
+       };
+
+       clk_apb: clk_apb@98100000 {
+               compatible = "moxa,moxart-apb-clock";
+               #clock-cells = <0>;
+               reg = <0x98100000 0x34>;
+               clocks = <&clk_pll>;
+       };
index a367a98317175f59745e5b61e6fdf175f29342bc..48a7ef3d05f6e8be632c767033bf21977b9fa7f3 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_EFM32)              += clk-efm32gg.o
 obj-$(CONFIG_ARCH_HIGHBANK)            += clk-highbank.o
 obj-$(CONFIG_MACH_LOONGSON1)           += clk-ls1x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)      += clk-max77686.o
+obj-$(CONFIG_ARCH_MOXART)              += clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)             += clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)              += clk-nspire.o
 obj-$(CONFIG_CLK_PPC_CORENET)          += clk-ppc-corenet.o
diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c
new file mode 100644 (file)
index 0000000..30a3b69
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * MOXA ART SoCs clock driver.
+ *
+ * Copyright (C) 2013 Jonas Jensen
+ *
+ * Jonas Jensen <jonas.jensen@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/clkdev.h>
+
+void __init moxart_of_pll_clk_init(struct device_node *node)
+{
+       static void __iomem *base;
+       struct clk *clk, *ref_clk;
+       unsigned int mul;
+       const char *name = node->name;
+       const char *parent_name;
+
+       of_property_read_string(node, "clock-output-names", &name);
+       parent_name = of_clk_get_parent_name(node, 0);
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s: of_iomap failed\n", node->full_name);
+               return;
+       }
+
+       mul = readl(base + 0x30) >> 3 & 0x3f;
+       iounmap(base);
+
+       ref_clk = of_clk_get(node, 0);
+       if (IS_ERR(ref_clk)) {
+               pr_err("%s: of_clk_get failed\n", node->full_name);
+               return;
+       }
+
+       clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register clock\n", node->full_name);
+               return;
+       }
+
+       clk_register_clkdev(clk, NULL, name);
+       of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
+              moxart_of_pll_clk_init);
+
+void __init moxart_of_apb_clk_init(struct device_node *node)
+{
+       static void __iomem *base;
+       struct clk *clk, *pll_clk;
+       unsigned int div, val;
+       unsigned int div_idx[] = { 2, 3, 4, 6, 8};
+       const char *name = node->name;
+       const char *parent_name;
+
+       of_property_read_string(node, "clock-output-names", &name);
+       parent_name = of_clk_get_parent_name(node, 0);
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s: of_iomap failed\n", node->full_name);
+               return;
+       }
+
+       val = readl(base + 0xc) >> 4 & 0x7;
+       iounmap(base);
+
+       if (val > 4)
+               val = 0;
+       div = div_idx[val] * 2;
+
+       pll_clk = of_clk_get(node, 0);
+       if (IS_ERR(pll_clk)) {
+               pr_err("%s: of_clk_get failed\n", node->full_name);
+               return;
+       }
+
+       clk = clk_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register clock\n", node->full_name);
+               return;
+       }
+
+       clk_register_clkdev(clk, NULL, name);
+       of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock",
+              moxart_of_apb_clk_init);
This page took 0.027667 seconds and 5 git commands to generate.