summaryrefslogtreecommitdiff
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
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>
-rw-r--r--arch/sh/Kconfig2
-rw-r--r--arch/sh/boards/board-sh7785lcr.c22
-rw-r--r--arch/sh/include/asm/clock.h2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7785.c203
4 files changed, 125 insertions, 104 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d7990cd2f8d4..df764c56b050 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -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"
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index 6f94f17adc46..33b194b0454d 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -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>
@@ -19,8 +19,11 @@
#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,
};
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index c27e844db0de..40cf3c07d7e6 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -34,7 +34,9 @@ struct clk {
unsigned long rate;
unsigned long flags;
+
unsigned long arch_flags;
+ void *priv;
};
struct clk_lookup {
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;
}