sh: clkfwk: Update SH7785 for refactored clock framework.
authorPaul Mundt <lethal@linux-sh.org>
Wed, 13 May 2009 08:55:00 +0000 (17:55 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 13 May 2009 08:55:00 +0000 (17:55 +0900)
This updates the SH7785 CPU code as well as the SH7785LCR board support
code for making use of the newly refactored clock framework. Support for
the legacy CPG clocks is dropped at this point, with the extal frequency
fed in from the board code.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/Kconfig
arch/sh/boards/board-sh7785lcr.c
arch/sh/include/asm/clock.h
arch/sh/kernel/cpu/sh4a/clock-sh7785.c

index d7990cd..df764c5 100644 (file)
@@ -514,7 +514,7 @@ config SH_PCLK_FREQ
          platforms lacking an RTC.
 
 config SH_CLK_CPG_LEGACY
-       def_bool y
+       def_bool y if !CPU_SUBTYPE_SH7785
 
 config SH_CLK_MD
        int "CPU Mode Pin Setting"
index 6f94f17..33b194b 100644 (file)
@@ -2,12 +2,12 @@
  * Renesas Technology Corp. R0P7785LC0011RL Support.
  *
  * Copyright (C) 2008  Yoshihiro Shimoda
+ * Copyright (C) 2009  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/sm501.h>
 #include <linux/i2c-pca-platform.h>
 #include <linux/i2c-algo-pca.h>
 #include <linux/irq.h>
-#include <asm/heartbeat.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
 #include <mach/sh7785lcr.h>
+#include <asm/heartbeat.h>
+#include <asm/clock.h>
 
 /*
  * NOTE: This board has 2 physical memory maps.
@@ -273,6 +276,20 @@ void __init init_sh7785lcr_IRQ(void)
        plat_irq_setup_pins(IRQ_MODE_IRQ3210);
 }
 
+static int sh7785lcr_clk_init(void)
+{
+       struct clk *clk;
+       int ret;
+
+       clk = clk_get(NULL, "extal");
+       if (!clk || IS_ERR(clk))
+               return PTR_ERR(clk);
+       ret = clk_set_rate(clk, 33333333);
+       clk_put(clk);
+
+       return ret;
+}
+
 static void sh7785lcr_power_off(void)
 {
        unsigned char *p;
@@ -309,6 +326,7 @@ static void __init sh7785lcr_setup(char **cmdline_p)
 static struct sh_machine_vector mv_sh7785lcr __initmv = {
        .mv_name                = "SH7785LCR",
        .mv_setup               = sh7785lcr_setup,
+       .mv_clk_init            = sh7785lcr_clk_init,
        .mv_init_irq            = init_sh7785lcr_IRQ,
 };
 
index c27e844..40cf3c0 100644 (file)
@@ -34,7 +34,9 @@ struct clk {
 
        unsigned long           rate;
        unsigned long           flags;
+
        unsigned long           arch_flags;
+       void                    *priv;
 };
 
 struct clk_lookup {
index bf5a0da..87584dc 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SH7785 support for the clock framework
  *
- *  Copyright (C) 2007  Paul Mundt
+ *  Copyright (C) 2007 - 2009  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
-#include <asm/io.h>
-
-static int ifc_divisors[] = { 1, 2, 4, 6 };
-static int ufc_divisors[] = { 1, 1, 4, 6 };
-static int sfc_divisors[] = { 1, 1, 4, 6 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18,
-                            24, 32, 36, 48, 1, 1, 1, 1 };
-static int mfc_divisors[] = { 1, 1, 4, 6 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18,
-                             24, 32, 36, 48, 1, 1, 1, 1 };
-
-static void master_clk_init(struct clk *clk)
-{
-       clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
-}
 
-static struct clk_ops sh7785_master_clk_ops = {
-       .init           = master_clk_init,
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+                              24, 32, 36, 48 };
+struct clk_priv {
+       unsigned int shift;
 };
 
-static unsigned long module_clk_recalc(struct clk *clk)
-{
-       int idx = (ctrl_inl(FRQMR1) & 0x000f);
-       return clk->parent->rate / pfc_divisors[idx];
-}
+#define FRQMR_CLK_DATA(_name, _shift)  \
+static struct clk_priv _name##_data = {        .shift = _shift, }
 
-static struct clk_ops sh7785_module_clk_ops = {
-       .recalc         = module_clk_recalc,
-};
+FRQMR_CLK_DATA(pfc,  0);
+FRQMR_CLK_DATA(s3fc, 4);
+FRQMR_CLK_DATA(s2fc, 8);
+FRQMR_CLK_DATA(mfc, 12);
+FRQMR_CLK_DATA(bfc, 16);
+FRQMR_CLK_DATA(sfc, 20);
+FRQMR_CLK_DATA(ufc, 24);
+FRQMR_CLK_DATA(ifc, 28);
 
-static unsigned long bus_clk_recalc(struct clk *clk)
+static unsigned long frqmr_clk_recalc(struct clk *clk)
 {
-       int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
-       return clk->parent->rate / bfc_divisors[idx];
-}
+       struct clk_priv *data = clk->priv;
+       unsigned int idx;
 
-static struct clk_ops sh7785_bus_clk_ops = {
-       .recalc         = bus_clk_recalc,
-};
+       idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f;
 
-static unsigned long cpu_clk_recalc(struct clk *clk)
-{
-       int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
-       return clk->parent->rate / ifc_divisors[idx];
+       /*
+        * XXX: PLL1 multiplier is locked for the default clock mode,
+        * when mode pin detection and configuration support is added,
+        * select the multiplier dynamically.
+        */
+       return clk->parent->rate * 36 / div2[idx];
 }
 
-static struct clk_ops sh7785_cpu_clk_ops = {
-       .recalc         = cpu_clk_recalc,
+static struct clk_ops frqmr_clk_ops = {
+       .recalc         = frqmr_clk_recalc,
 };
 
-static struct clk_ops *sh7785_clk_ops[] = {
-       &sh7785_master_clk_ops,
-       &sh7785_module_clk_ops,
-       &sh7785_bus_clk_ops,
-       &sh7785_cpu_clk_ops,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+       .name           = "extal",
+       .id             = -1,
+       .rate           = 33333333,
 };
 
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-       if (idx < ARRAY_SIZE(sh7785_clk_ops))
-               *ops = sh7785_clk_ops[idx];
-}
-
-static unsigned long shyway_clk_recalc(struct clk *clk)
-{
-       int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
-       return clk->parent->rate / sfc_divisors[idx];
-}
-
-static struct clk_ops sh7785_shyway_clk_ops = {
-       .recalc         = shyway_clk_recalc,
+static struct clk cpu_clk = {
+       .name           = "cpu_clk",            /* Ick */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+       .priv           = &ifc_data,
 };
 
-static struct clk sh7785_shyway_clk = {
-       .name           = "shyway_clk",
+static struct clk shyway_clk = {
+       .name           = "shyway_clk",         /* SHck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
        .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &sh7785_shyway_clk_ops,
+       .priv           = &sfc_data,
 };
 
-static unsigned long ddr_clk_recalc(struct clk *clk)
-{
-       int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
-       return clk->parent->rate / mfc_divisors[idx];
-}
+static struct clk peripheral_clk = {
+       .name           = "peripheral_clk",     /* Pck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+       .priv           = &pfc_data,
+};
 
-static struct clk_ops sh7785_ddr_clk_ops = {
-       .recalc         = ddr_clk_recalc,
+static struct clk ddr_clk = {
+       .name           = "ddr_clk",            /* DDRck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+       .priv           = &mfc_data,
 };
 
-static struct clk sh7785_ddr_clk = {
-       .name           = "ddr_clk",
+static struct clk bus_clk = {
+       .name           = "bus_clk",            /* Bck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
        .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &sh7785_ddr_clk_ops,
+       .priv           = &bfc_data,
 };
 
-static unsigned long ram_clk_recalc(struct clk *clk)
-{
-       int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003);
-       return clk->parent->rate / ufc_divisors[idx];
-}
+static struct clk ga_clk = {
+       .name           = "ga_clk",             /* GAck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
+       .priv           = &s2fc_data,
+};
 
-static struct clk_ops sh7785_ram_clk_ops = {
-       .recalc         = ram_clk_recalc,
+static struct clk du_clk = {
+       .name           = "du_clk",             /* DUck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
+       .priv           = &s3fc_data,
 };
 
-static struct clk sh7785_ram_clk = {
-       .name           = "ram_clk",
+static struct clk umem_clk = {
+       .name           = "umem_clk",           /* uck */
+       .id             = -1,
+       .ops            = &frqmr_clk_ops,
+       .parent         = &extal_clk,
        .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &sh7785_ram_clk_ops,
+       .priv           = &ufc_data,
 };
 
-/*
- * Additional SH7785-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *sh7785_onchip_clocks[] = {
-       &sh7785_shyway_clk,
-       &sh7785_ddr_clk,
-       &sh7785_ram_clk,
+static struct clk *clks[] = {
+       &extal_clk,
+       &cpu_clk,
+       &shyway_clk,
+       &peripheral_clk,
+       &ddr_clk,
+       &bus_clk,
+       &ga_clk,
+       &du_clk,
+       &umem_clk,
 };
 
 int __init arch_clk_init(void)
 {
-       struct clk *clk;
        int i, ret = 0;
 
-       cpg_clk_init();
-
-       clk = clk_get(NULL, "master_clk");
-       for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) {
-               struct clk *clkp = sh7785_onchip_clocks[i];
-
-               clkp->parent = clk;
-               ret |= clk_register(clkp);
-       }
-
-       clk_put(clk);
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               ret |= clk_register(clks[i]);
 
        return ret;
 }