ARM: integrator: convert to common clock
authorLinus Walleij <linus.walleij@linaro.org>
Mon, 11 Jun 2012 15:33:12 +0000 (17:33 +0200)
committerMike Turquette <mturquette@linaro.org>
Thu, 12 Jul 2012 00:58:45 +0000 (17:58 -0700)
This converts the Integrator platform to use common clock
and the ICST driver. Since from this point not all ARM
reference platforms use the clock, we define
CONFIG_PLAT_VERSATILE_CLOCK and select it for all platforms
except the Integrator.

Open issue: I could not use the .init_early() field of the
machine descriptor to initialize the clocks, but had to
move them to .init_irq(), so presumably .init_early() is
so early that common clock is not up, and .init_machine()
is too late since it's needed for the clockevent/clocksource
initialization. Any suggestions on how to solve this is
very welcome.

Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
[mturquette@linaro.org: use 'select' instead of versatile Kconfig]
Signed-off-by: Mike Turquette <mturquette@linaro.org>
arch/arm/Kconfig
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/include/mach/clkdev.h [deleted file]
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/plat-versatile/Kconfig
arch/arm/plat-versatile/Makefile
drivers/clk/versatile/Makefile
drivers/clk/versatile/clk-integrator.c [new file with mode: 0644]
include/linux/platform_data/clk-integrator.h [new file with mode: 0644]

index c598537..6f8cf40 100644 (file)
@@ -254,8 +254,8 @@ config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
        select ARCH_HAS_CPUFREQ
-       select CLKDEV_LOOKUP
-       select HAVE_MACH_CLKDEV
+       select COMMON_CLK
+       select CLK_VERSATILE
        select HAVE_TCM
        select ICST
        select GENERIC_CLOCKEVENTS
@@ -277,6 +277,7 @@ config ARCH_REALVIEW
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        select ARM_TIMER_SP804
        select GPIO_PL061 if GPIOLIB
@@ -295,6 +296,7 @@ config ARCH_VERSATILE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select NEED_MACH_IO_H if PCI
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        select PLAT_VERSATILE_FPGA_IRQ
        select ARM_TIMER_SP804
@@ -314,6 +316,7 @@ config ARCH_VEXPRESS
        select ICST
        select NO_IOPORT
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        help
          This enables support for the ARM Ltd Versatile Express boards.
index 2a20bba..ebf680b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
-#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -61,50 +60,6 @@ static struct amba_device *amba_devs[] __initdata = {
        &kmi1_device,
 };
 
-/*
- * These are fixed clocks.
- */
-static struct clk clk24mhz = {
-       .rate   = 24000000,
-};
-
-static struct clk uartclk = {
-       .rate   = 14745600,
-};
-
-static struct clk dummy_apb_pclk;
-
-static struct clk_lookup lookups[] = {
-       {       /* Bus clock */
-               .con_id         = "apb_pclk",
-               .clk            = &dummy_apb_pclk,
-       }, {
-               /* Integrator/AP timer frequency */
-               .dev_id         = "ap_timer",
-               .clk            = &clk24mhz,
-       }, {    /* UART0 */
-               .dev_id         = "uart0",
-               .clk            = &uartclk,
-       }, {    /* UART1 */
-               .dev_id         = "uart1",
-               .clk            = &uartclk,
-       }, {    /* KMI0 */
-               .dev_id         = "kmi0",
-               .clk            = &clk24mhz,
-       }, {    /* KMI1 */
-               .dev_id         = "kmi1",
-               .clk            = &clk24mhz,
-       }, {    /* MMCI - IntegratorCP */
-               .dev_id         = "mmci",
-               .clk            = &uartclk,
-       }
-};
-
-void __init integrator_init_early(void)
-{
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
-
 static int __init integrator_init(void)
 {
        int i;
diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h
deleted file mode 100644 (file)
index bfe0767..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#include <linux/module.h>
-#include <plat/clock.h>
-
-struct clk {
-       unsigned long           rate;
-       const struct clk_ops    *ops;
-       struct module           *owner;
-       const struct icst_params *params;
-       void __iomem            *vcoreg;
-       void                    *data;
-};
-
-static inline int __clk_get(struct clk *clk)
-{
-       return try_module_get(clk->owner);
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-       module_put(clk->owner);
-}
-
-#endif
index c857501..7b1055c 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/mtd/physmap.h>
 #include <linux/clk.h>
+#include <linux/platform_data/clk-integrator.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -174,6 +175,7 @@ static void __init ap_init_irq(void)
 
        fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
                -1, INTEGRATOR_SC_VALID_INT, NULL);
+       integrator_clk_init(false);
 }
 
 #ifdef CONFIG_PM
@@ -440,6 +442,10 @@ static void integrator_clockevent_init(unsigned long inrate)
                                        0xffffU);
 }
 
+void __init ap_init_early(void)
+{
+}
+
 /*
  * Set up timer(s).
  */
@@ -471,7 +477,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
        .reserve        = integrator_reserve,
        .map_io         = ap_map_io,
        .nr_irqs        = NR_IRQS_INTEGRATOR_AP,
-       .init_early     = integrator_init_early,
+       .init_early     = ap_init_early,
        .init_irq       = ap_init_irq,
        .handle_irq     = fpga_handle_irq,
        .timer          = &ap_timer,
index a8c6480..82d5c83 100644 (file)
@@ -21,8 +21,8 @@
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
-#include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_data/clk-integrator.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -171,64 +171,9 @@ static void __init intcp_init_irq(void)
 
        fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
                      IRQ_CP_CPPLDINT, sic_mask, NULL);
+       integrator_clk_init(true);
 }
 
-/*
- * Clock handling
- */
-#define CM_LOCK                (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
-#define CM_AUXOSC      (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
-
-static const struct icst_params cp_auxvco_params = {
-       .ref            = 24000000,
-       .vco_max        = ICST525_VCO_MAX_5V,
-       .vco_min        = ICST525_VCO_MIN,
-       .vd_min         = 8,
-       .vd_max         = 263,
-       .rd_min         = 3,
-       .rd_max         = 65,
-       .s2div          = icst525_s2div,
-       .idx2s          = icst525_idx2s,
-};
-
-static void cp_auxvco_set(struct clk *clk, struct icst_vco vco)
-{
-       u32 val;
-
-       val = readl(clk->vcoreg) & ~0x7ffff;
-       val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-       writel(0xa05f, CM_LOCK);
-       writel(val, clk->vcoreg);
-       writel(0, CM_LOCK);
-}
-
-static const struct clk_ops cp_auxclk_ops = {
-       .round  = icst_clk_round,
-       .set    = icst_clk_set,
-       .setvco = cp_auxvco_set,
-};
-
-static struct clk cp_auxclk = {
-       .ops    = &cp_auxclk_ops,
-       .params = &cp_auxvco_params,
-       .vcoreg = CM_AUXOSC,
-};
-
-static struct clk sp804_clk = {
-       .rate   = 1000000,
-};
-
-static struct clk_lookup cp_lookups[] = {
-       {       /* CLCD */
-               .dev_id         = "clcd",
-               .clk            = &cp_auxclk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .clk            = &sp804_clk,
-       },
-};
-
 /*
  * Flash handling.
  */
@@ -406,10 +351,6 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static void __init intcp_init_early(void)
 {
-       clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
-
-       integrator_init_early();
-
 #ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
        versatile_sched_clock_init(REFCOUNTER, 24000000);
 #endif
index 81ee7cc..8d5c10a 100644 (file)
@@ -1,5 +1,8 @@
 if PLAT_VERSATILE
 
+config PLAT_VERSATILE_CLOCK
+       bool
+
 config PLAT_VERSATILE_CLCD
        bool
 
index a5cb194..272769a 100644 (file)
@@ -1,4 +1,4 @@
-obj-y  := clock.o
+obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
 obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
 obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
 obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
index a83539b..50cf6a2 100644 (file)
@@ -1,2 +1,3 @@
 # Makefile for Versatile-specific clocks
 obj-$(CONFIG_ICST)             += clk-icst.o
+obj-$(CONFIG_ARCH_INTEGRATOR)  += clk-integrator.o
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
new file mode 100644 (file)
index 0000000..a505392
--- /dev/null
@@ -0,0 +1,111 @@
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#include "clk-icst.h"
+
+/*
+ * Implementation of the ARM Integrator/AP and Integrator/CP clock tree.
+ * Inspired by portions of:
+ * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
+ */
+#define CM_LOCK                (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
+#define CM_AUXOSC      (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
+
+/**
+ * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
+ * @vco: ICST VCO parameters to update with hardware status
+ */
+static struct icst_vco cp_auxvco_get(void)
+{
+       u32 val;
+       struct icst_vco vco;
+
+       val = readl(CM_AUXOSC);
+       vco.v = val & 0x1ff;
+       vco.r = (val >> 9) & 0x7f;
+       vco.s = (val >> 16) & 03;
+       return vco;
+}
+
+/**
+ * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
+ * @vco: ICST VCO parameters to commit
+ */
+static void cp_auxvco_set(struct icst_vco vco)
+{
+       u32 val;
+
+       val = readl(CM_AUXOSC) & ~0x7ffff;
+       val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+       /* This magic unlocks the CM VCO so it can be controlled */
+       writel(0xa05f, CM_LOCK);
+       writel(val, CM_AUXOSC);
+       /* This locks the CM again */
+       writel(0, CM_LOCK);
+}
+
+static const struct icst_params cp_auxvco_params = {
+       .ref            = 24000000,
+       .vco_max        = ICST525_VCO_MAX_5V,
+       .vco_min        = ICST525_VCO_MIN,
+       .vd_min         = 8,
+       .vd_max         = 263,
+       .rd_min         = 3,
+       .rd_max         = 65,
+       .s2div          = icst525_s2div,
+       .idx2s          = icst525_idx2s,
+};
+
+static const struct clk_icst_desc __initdata cp_icst_desc = {
+       .params = &cp_auxvco_params,
+       .getvco = cp_auxvco_get,
+       .setvco = cp_auxvco_set,
+};
+
+/*
+ * integrator_clk_init() - set up the integrator clock tree
+ * @is_cp: pass true if it's the Integrator/CP else AP is assumed
+ */
+void __init integrator_clk_init(bool is_cp)
+{
+       struct clk *clk;
+
+       /* APB clock dummy */
+       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
+       clk_register_clkdev(clk, "apb_pclk", NULL);
+
+       /* UART reference clock */
+       clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
+                               14745600);
+       clk_register_clkdev(clk, NULL, "uart0");
+       clk_register_clkdev(clk, NULL, "uart1");
+       if (is_cp)
+               clk_register_clkdev(clk, NULL, "mmci");
+
+       /* 24 MHz clock */
+       clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
+                               24000000);
+       clk_register_clkdev(clk, NULL, "kmi0");
+       clk_register_clkdev(clk, NULL, "kmi1");
+       if (!is_cp)
+               clk_register_clkdev(clk, NULL, "ap_timer");
+
+       if (!is_cp)
+               return;
+
+       /* 1 MHz clock */
+       clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
+                               1000000);
+       clk_register_clkdev(clk, NULL, "sp804");
+
+       /* ICST VCO clock used on the Integrator/CP CLCD */
+       clk = icst_clk_register(NULL, &cp_icst_desc);
+       clk_register_clkdev(clk, NULL, "clcd");
+}
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h
new file mode 100644 (file)
index 0000000..83fe9c2
--- /dev/null
@@ -0,0 +1 @@
+void integrator_clk_init(bool is_cp);