clk: move IM-PD1 clocks to drivers/clk
authorLinus Walleij <linus.walleij@linaro.org>
Tue, 20 Nov 2012 21:39:49 +0000 (22:39 +0100)
committerMike Turquette <mturquette@linaro.org>
Wed, 21 Nov 2012 19:02:44 +0000 (11:02 -0800)
The ARM IM-PD1 add-on module has a few clock of its own, let's
move also these down to the drivers/clk/versatile driver dir
and get rid of any remaining oldschool Integrator clocks.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
arch/arm/mach-integrator/impd1.c
drivers/clk/versatile/Makefile
drivers/clk/versatile/clk-impd1.c [new file with mode: 0644]
include/linux/platform_data/clk-integrator.h

index e428f3ab15c75519e3aa7a3ceda3728228d1831e..b3d86d7081a01b80fbf1123721b7c2e8a20e3596 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
 #include <linux/slab.h>
-#include <linux/clkdev.h>
 
-#include <asm/hardware/icst.h>
 #include <mach/lm.h>
 #include <mach/impd1.h>
 #include <asm/sizes.h>
@@ -36,45 +35,6 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
 
 struct impd1_module {
        void __iomem    *base;
-       struct clk      vcos[2];
-       struct clk_lookup *clks[3];
-};
-
-static const struct icst_params impd1_vco_params = {
-       .ref            = 24000000,     /* 24 MHz */
-       .vco_max        = ICST525_VCO_MAX_3V,
-       .vco_min        = ICST525_VCO_MIN,
-       .vd_min         = 12,
-       .vd_max         = 519,
-       .rd_min         = 3,
-       .rd_max         = 120,
-       .s2div          = icst525_s2div,
-       .idx2s          = icst525_idx2s,
-};
-
-static void impd1_setvco(struct clk *clk, struct icst_vco vco)
-{
-       struct impd1_module *impd1 = clk->data;
-       u32 val = vco.v | (vco.r << 9) | (vco.s << 16);
-
-       writel(0xa05f, impd1->base + IMPD1_LOCK);
-       writel(val, clk->vcoreg);
-       writel(0, impd1->base + IMPD1_LOCK);
-
-#ifdef DEBUG
-       vco.v = val & 0x1ff;
-       vco.r = (val >> 9) & 0x7f;
-       vco.s = (val >> 16) & 7;
-
-       pr_debug("IM-PD1: VCO%d clock is %ld Hz\n",
-                vconr, icst525_hz(&impd1_vco_params, vco));
-#endif
-}
-
-static const struct clk_ops impd1_clk_ops = {
-       .round  = icst_clk_round,
-       .set    = icst_clk_set,
-       .setvco = impd1_setvco,
 };
 
 void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -344,10 +304,6 @@ static struct impd1_device impd1_devs[] = {
        }
 };
 
-static struct clk fixed_14745600 = {
-       .rate = 14745600,
-};
-
 static int impd1_probe(struct lm_device *dev)
 {
        struct impd1_module *impd1;
@@ -376,23 +332,7 @@ static int impd1_probe(struct lm_device *dev)
        printk("IM-PD1 found at 0x%08lx\n",
                (unsigned long)dev->resource.start);
 
-       for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
-               impd1->vcos[i].ops = &impd1_clk_ops,
-               impd1->vcos[i].owner = THIS_MODULE,
-               impd1->vcos[i].params = &impd1_vco_params,
-               impd1->vcos[i].data = impd1;
-       }
-       impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1;
-       impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2;
-
-       impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000",
-                                       dev->id);
-       impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100",
-                                       dev->id);
-       impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200",
-                                       dev->id);
-       for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
-               clkdev_add(impd1->clks[i]);
+       integrator_impd1_clk_init(impd1->base, dev->id);
 
        for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
                struct impd1_device *idev = impd1_devs + i;
@@ -431,12 +371,9 @@ static int impd1_remove_one(struct device *dev, void *data)
 static void impd1_remove(struct lm_device *dev)
 {
        struct impd1_module *impd1 = lm_get_drvdata(dev);
-       int i;
 
        device_for_each_child(&dev->dev, NULL, impd1_remove_one);
-
-       for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
-               clkdev_drop(impd1->clks[i]);
+       integrator_impd1_clk_exit(dev->id);
 
        lm_set_drvdata(dev, NULL);
 
index c776053e5bb48295bbf45b632b5ab336940254b9..ec3b88fe3e6db56a213107daf6fc1b03ea524785 100644 (file)
@@ -1,6 +1,7 @@
 # Makefile for Versatile-specific clocks
 obj-$(CONFIG_ICST)             += clk-icst.o
 obj-$(CONFIG_ARCH_INTEGRATOR)  += clk-integrator.o
+obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)    += clk-realview.o
 obj-$(CONFIG_ARCH_VEXPRESS)    += clk-vexpress.o
 obj-$(CONFIG_VEXPRESS_CONFIG)  += clk-vexpress-osc.o
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
new file mode 100644 (file)
index 0000000..369139a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Clock driver for the ARM Integrator/IM-PD1 board
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * 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/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
+
+#include <mach/impd1.h>
+
+#include "clk-icst.h"
+
+struct impd1_clk {
+       struct clk *vcoclk;
+       struct clk *uartclk;
+       struct clk_lookup *clks[3];
+};
+
+static struct impd1_clk impd1_clks[4];
+
+/*
+ * There are two VCO's on the IM-PD1 but only one is used by the
+ * kernel, that is why we are only implementing the control of
+ * IMPD1_OSC1 here.
+ */
+
+static const struct icst_params impd1_vco_params = {
+       .ref            = 24000000,     /* 24 MHz */
+       .vco_max        = ICST525_VCO_MAX_3V,
+       .vco_min        = ICST525_VCO_MIN,
+       .vd_min         = 12,
+       .vd_max         = 519,
+       .rd_min         = 3,
+       .rd_max         = 120,
+       .s2div          = icst525_s2div,
+       .idx2s          = icst525_idx2s,
+};
+
+static const struct clk_icst_desc impd1_icst1_desc = {
+       .params = &impd1_vco_params,
+       .vco_offset = IMPD1_OSC1,
+       .lock_offset = IMPD1_LOCK,
+};
+
+/**
+ * integrator_impd1_clk_init() - set up the integrator clock tree
+ * @base: base address of the logic module (LM)
+ * @id: the ID of this LM
+ */
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
+{
+       struct impd1_clk *imc;
+       struct clk *clk;
+       int i;
+
+       if (id > 3) {
+               pr_crit("no more than 4 LMs can be attached\n");
+               return;
+       }
+       imc = &impd1_clks[id];
+
+       clk = icst_clk_register(NULL, &impd1_icst1_desc, base);
+       imc->vcoclk = clk;
+       imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
+
+       /* UART reference clock */
+       clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
+                               14745600);
+       imc->uartclk = clk;
+       imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
+       imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
+
+       for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+               clkdev_add(imc->clks[i]);
+}
+
+void integrator_impd1_clk_exit(unsigned int id)
+{
+       int i;
+       struct impd1_clk *imc;
+
+       if (id > 3)
+               return;
+       imc = &impd1_clks[id];
+
+       for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+               clkdev_drop(imc->clks[i]);
+       clk_unregister(imc->uartclk);
+       clk_unregister(imc->vcoclk);
+}
index 83fe9c283bb8efa5486aa131def9e16d4846d4ca..280edac9d0a5ca75185f151eb88cc3f362c695b7 100644 (file)
@@ -1 +1,3 @@
 void integrator_clk_init(bool is_cp);
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id);
+void integrator_impd1_clk_exit(unsigned int id);