OSDN Git Service

sh: SH7206 clock framework suooprt
authorYoshinori Sato <ysato@users.sourceforge.jp>
Tue, 23 Jun 2015 04:10:07 +0000 (13:10 +0900)
committerYoshinori Sato <ysato@users.sourceforge.jp>
Tue, 23 Jun 2015 04:10:07 +0000 (13:10 +0900)
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
arch/sh/Kconfig
arch/sh/boards/mach-se/7206/setup.c
arch/sh/kernel/cpu/sh2a/clock-sh7206.c

index 42564ab..e96d632 100644 (file)
@@ -588,7 +588,7 @@ config SH_CLK_CPG_LEGACY
        def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
                      !CPU_SHX3 && !CPU_SUBTYPE_SH7757 && \
                      !CPU_SUBTYPE_SH7734 && !CPU_SUBTYPE_SH7264 && \
-                     !CPU_SUBTYPE_SH7269
+                     !CPU_SUBTYPE_SH7269 && !CPU_SUBTYPE_SH7206
 
 endmenu
 
index 68883ec..e7a2d30 100644 (file)
@@ -81,7 +81,7 @@ device_initcall(se7206_devices_setup);
 
 static int se7206_mode_pins(void)
 {
-       return MODE_PIN1 | MODE_PIN2;
+       return MODE_PIN2|MODE_PIN1;
 }
 
 /*
index 1777898..91372ce 100644 (file)
  *
  * SH7206 support for the clock framework
  *
- *  Copyright (C) 2006  Yoshinori Sato
+ *  Copyright (C) 2014  Yoshinori Sato
  *
- * Based on clock-sh4.c
- *  Copyright (C) 2005  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/kernel.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
-#include <asm/freq.h>
 #include <asm/io.h>
 
+#define FRQCR 0xfffe0010
+#define MCLKCR 0xfffe0410
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
 static const int pll1rate[]={1,2,3,4,6,8};
-static const int pfc_divisors[]={1,2,3,4,6,8,12};
-#define ifc_divisors pfc_divisors
 
 static unsigned int pll2_mult;
 
-static void master_clk_init(struct clk *clk)
+static struct clk extal_clk = {
+       .rate           = 33333333,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
 {
-       clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+       unsigned long rate = clk->parent->rate * pll2_mult;
+       return rate * pll1rate[(__raw_readw(FRQCR) >> 8) & 7];
 }
 
-static struct sh_clk_ops sh7206_master_clk_ops = {
-       .init           = master_clk_init,
+static struct sh_clk_ops pll_clk_ops = {
+       .recalc         = pll_recalc,
 };
 
-static unsigned long module_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readw(FREQCR) & 0x0007);
-       return clk->parent->rate / pfc_divisors[idx];
-}
+static struct clk pll_clk = {
+       .ops            = &pll_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+};
 
-static struct sh_clk_ops sh7206_module_clk_ops = {
-       .recalc         = module_clk_recalc,
+struct clk *main_clks[] = {
+       &extal_clk,
+       &pll_clk,
 };
 
-static unsigned long bus_clk_recalc(struct clk *clk)
-{
-       return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
-}
+static int div1[] = { 1, 2, 3, 4, 6, 8, 12 };
 
-static struct sh_clk_ops sh7206_bus_clk_ops = {
-       .recalc         = bus_clk_recalc,
+static struct clk_div_mult_table div_div_mult_table = {
+       .divisors = div1,
+       .nr_divisors = ARRAY_SIZE(div1),
 };
 
-static unsigned long cpu_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readw(FREQCR) & 0x0007);
-       return clk->parent->rate / ifc_divisors[idx];
+static struct clk_div4_table div_table = {
+       .div_mult_table = &div_div_mult_table,
+};
+
+#define SH_CLK_DIV(_parent, _reg, _shift, _div_bitmap, _mask, _flags)  \
+{                                                              \
+       .parent = _parent,                                      \
+       .enable_reg = (void __iomem *)_reg,                     \
+       .enable_bit = _shift,                                   \
+       .arch_flags = _div_bitmap,                              \
+       .div_mask = _mask,                                      \
+       .flags = _flags,                                        \
 }
 
-static struct sh_clk_ops sh7206_cpu_clk_ops = {
-       .recalc         = cpu_clk_recalc,
+struct clk div_clks[] = {
+       SH_CLK_DIV(&pll_clk, FRQCR, 4, 0, 0x07, CLK_ENABLE_REG_16BIT), /* I */
+       SH_CLK_DIV(&pll_clk, FRQCR, 8, 0, 0x07, CLK_ENABLE_REG_16BIT), /* B */
+       SH_CLK_DIV(&pll_clk, FRQCR, 0, 0, 0x07, CLK_ENABLE_REG_16BIT), /* P */
+       SH_CLK_DIV(&pll_clk, MCLKCR, 0, 0, 0x03, CLK_ENABLE_REG_8BIT), /* MTU */
+};
+
+static struct clk mstp_clks[] = {
+       SH_CLK_MSTP8(&div_clks[2], STBCR4, 7, 0), /* SCIF0 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR4, 6, 0), /* SCIF1 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR4, 5, 0), /* SCIF2 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR4, 4, 0), /* SCIF3 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR4, 2, 0), /* CMT */
+       SH_CLK_MSTP8(&div_clks[3], STBCR3, 6, 0), /* MTU2S */
+       SH_CLK_MSTP8(&div_clks[3], STBCR3, 5, 0), /* MTU2 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR3, 4, 1), /* POE2 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR3, 3, 1), /* IIC3 */
+       SH_CLK_MSTP8(&div_clks[2], STBCR3, 2, 1), /* ADC */
+       SH_CLK_MSTP8(&div_clks[2], STBCR3, 1, 1), /* DAC */
 };
 
-static struct sh_clk_ops *sh7206_clk_ops[] = {
-       &sh7206_master_clk_ops,
-       &sh7206_module_clk_ops,
-       &sh7206_bus_clk_ops,
-       &sh7206_cpu_clk_ops,
+static struct clk_lookup lookups[] = {
+       /* main clocks */
+       CLKDEV_CON_ID("extal", &extal_clk),
+       CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("cpu_clk", &div_clks[0]),
+       CLKDEV_CON_ID("bus_clk", &div_clks[1]),
+       CLKDEV_CON_ID("peripheral_clk", &div_clks[2]),
+       CLKDEV_CON_ID("mtu_clk", &div_clks[3]),
+
+       /* MSTP clocks */
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[0]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[2]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[3]),
+       CLKDEV_CON_ID("cmt_fck", &mstp_clks[4]),
+       CLKDEV_CON_ID("mtu2s_fck", &mstp_clks[5]),
+       CLKDEV_CON_ID("mtu2_fck", &mstp_clks[6]),
+       CLKDEV_CON_ID("poe", &mstp_clks[7]),
+       CLKDEV_CON_ID("iic", &mstp_clks[8]),
+       CLKDEV_CON_ID("adc0", &mstp_clks[9]),
+       CLKDEV_CON_ID("dac0", &mstp_clks[10]),
 };
 
-void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
+int __init arch_clk_init(void)
 {
-       if (test_mode_pin(MODE_PIN2 | MODE_PIN1 | MODE_PIN0))
+       int i, ret = 0;
+
+       if (test_mode_pin(MODE_PIN2 | MODE_PIN1 | MODE_PIN0) ==
+           (MODE_PIN2 | MODE_PIN1 | MODE_PIN0))
                pll2_mult = 1;
-       else if (test_mode_pin(MODE_PIN2 | MODE_PIN1))
+       else if (test_mode_pin(MODE_PIN2 | MODE_PIN1) ==
+                (MODE_PIN2 | MODE_PIN1))
                pll2_mult = 2;
-       else if (test_mode_pin(MODE_PIN1))
+       else if (test_mode_pin(MODE_PIN1) == MODE_PIN1)
                pll2_mult = 4;
 
-       if (idx < ARRAY_SIZE(sh7206_clk_ops))
-               *ops = sh7206_clk_ops[idx];
+       for (i = 0; !ret && (i < ARRAY_SIZE(main_clks)); i++)
+               ret = clk_register(main_clks[i]);
+
+       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+       if (!ret)
+               ret = sh_clk_div4_register(div_clks, ARRAY_SIZE(div_clks),
+                                          &div_table);
+
+       if (!ret)
+               ret = sh_clk_mstp_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+
+       return ret;
 }