2 * arch/sh/kernel/cpu/sh4a/clock-sh7786.c
4 * SH7786 support for the clock framework
6 * Copyright (C) 2008, 2009 Renesas Solutions Corp.
7 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
10 * Copyright (C) 2007 Paul Mundt
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file "COPYING" in the main directory of this archive
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <asm/clock.h>
22 static int ifc_divisors[] = { 1, 2, 4, 1 };
23 static int sfc_divisors[] = { 1, 1, 4, 1 };
24 static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 1,
25 24, 32, 1, 1, 1, 1, 1, 1 };
26 static int mfc_divisors[] = { 1, 1, 4, 1 };
27 static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 16, 1,
28 24, 32, 1, 48, 1, 1, 1, 1 };
30 static void master_clk_init(struct clk *clk)
32 clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
35 static struct clk_ops sh7786_master_clk_ops = {
36 .init = master_clk_init,
39 static void module_clk_recalc(struct clk *clk)
41 int idx = (ctrl_inl(FRQMR1) & 0x000f);
42 clk->rate = clk->parent->rate / pfc_divisors[idx];
45 static struct clk_ops sh7786_module_clk_ops = {
46 .recalc = module_clk_recalc,
49 static void bus_clk_recalc(struct clk *clk)
51 int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
52 clk->rate = clk->parent->rate / bfc_divisors[idx];
55 static struct clk_ops sh7786_bus_clk_ops = {
56 .recalc = bus_clk_recalc,
59 static void cpu_clk_recalc(struct clk *clk)
61 int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
62 clk->rate = clk->parent->rate / ifc_divisors[idx];
65 static struct clk_ops sh7786_cpu_clk_ops = {
66 .recalc = cpu_clk_recalc,
69 static struct clk_ops *sh7786_clk_ops[] = {
70 &sh7786_master_clk_ops,
71 &sh7786_module_clk_ops,
76 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
78 if (idx < ARRAY_SIZE(sh7786_clk_ops))
79 *ops = sh7786_clk_ops[idx];
82 static void shyway_clk_recalc(struct clk *clk)
84 int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
85 clk->rate = clk->parent->rate / sfc_divisors[idx];
88 static struct clk_ops sh7786_shyway_clk_ops = {
89 .recalc = shyway_clk_recalc,
92 static struct clk sh7786_shyway_clk = {
94 .flags = CLK_ALWAYS_ENABLED,
95 .ops = &sh7786_shyway_clk_ops,
98 static void ddr_clk_recalc(struct clk *clk)
100 int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
101 clk->rate = clk->parent->rate / mfc_divisors[idx];
104 static struct clk_ops sh7786_ddr_clk_ops = {
105 .recalc = ddr_clk_recalc,
108 static struct clk sh7786_ddr_clk = {
110 .flags = CLK_ALWAYS_ENABLED,
111 .ops = &sh7786_ddr_clk_ops,
115 * Additional SH7786-specific on-chip clocks that aren't already part of the
118 static struct clk *sh7786_onchip_clocks[] = {
123 static int __init sh7786_clk_init(void)
125 struct clk *clk = clk_get(NULL, "master_clk");
128 for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) {
129 struct clk *clkp = sh7786_onchip_clocks[i];
137 * Now that we have the rest of the clocks registered, we need to
138 * force the parent clock to propagate so that these clocks will
139 * automatically figure out their rate. We cheat by handing the
140 * parent clock its current rate and forcing child propagation.
142 clk_set_rate(clk, clk_get_rate(clk));
148 arch_initcall(sh7786_clk_init);