summaryrefslogtreecommitdiff
path: root/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-05-13 17:55:00 +0900
committerPaul Mundt <lethal@linux-sh.org>2009-05-13 17:55:00 +0900
commita77b5ac0ea8e47c77008d3a9a9976dcfbc01c42a (patch)
tree981fb1cf5b98a5e98a0c02e9dd2f950dc2759231 /arch/sh/kernel/cpu/sh4a/clock-sh7785.c
parent253b0887b3736160feac9ccdcf146a2073e41463 (diff)
sh: clkfwk: Update SH7785 for refactored clock framework.
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>
Diffstat (limited to 'arch/sh/kernel/cpu/sh4a/clock-sh7785.c')
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7785.c203
1 files changed, 102 insertions, 101 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
index bf5a0dacf8e5..87584dc81926 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
@@ -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
@@ -11,145 +11,146 @@
*/
#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;
}