aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-19 05:37:14 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-01-19 05:37:14 -0500
commit43a1839cb1e0e0ed08b8ace0adb3716865fd0c4c (patch)
tree9076b72e1cb925a2a6cef4aba381b0d9d9e151e4 /arch/sh/kernel/cpu/sh4a/clock-sh7786.c
parenta4ae2b2b18d1766768987dc5de42dfa3c2a6d9f7 (diff)
sh: SH7786 clock framework rewrite.
This rewrites the SH7786 clock framework support completely. It's reworked to provide all of the DIV4 and MSTP function clocks. This brings it in line with the current clock framework code and lets us drop SH7786 from the list of CPUs that require legacy CPG handling. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/cpu/sh4a/clock-sh7786.c')
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7786.c184
1 files changed, 88 insertions, 96 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
index a0e8869071a..494c636012b 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
@@ -3,11 +3,7 @@
3 * 3 *
4 * SH7786 support for the clock framework 4 * SH7786 support for the clock framework
5 * 5 *
6 * Copyright (C) 2008, 2009 Renesas Solutions Corp. 6 * Copyright (C) 2010 Paul Mundt
7 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
8 *
9 * Based on SH7785
10 * Copyright (C) 2007 Paul Mundt
11 * 7 *
12 * This file is subject to the terms and conditions of the GNU General Public 8 * 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 9 * License. See the file "COPYING" in the main directory of this archive
@@ -15,127 +11,123 @@
15 */ 11 */
16#include <linux/init.h> 12#include <linux/init.h>
17#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/clk.h>
15#include <linux/io.h>
18#include <asm/clock.h> 16#include <asm/clock.h>
19#include <asm/freq.h> 17#include <asm/freq.h>
20#include <asm/io.h>
21
22static int ifc_divisors[] = { 1, 2, 4, 1 };
23static int sfc_divisors[] = { 1, 1, 4, 1 };
24static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 1,
25 24, 32, 1, 1, 1, 1, 1, 1 };
26static int mfc_divisors[] = { 1, 1, 4, 1 };
27static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 16, 1,
28 24, 32, 1, 48, 1, 1, 1, 1 };
29
30static void master_clk_init(struct clk *clk)
31{
32 clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
33}
34 18
35static struct clk_ops sh7786_master_clk_ops = { 19/*
36 .init = master_clk_init, 20 * Default rate for the root input clock, reset this with clk_set_rate()
21 * from the platform code.
22 */
23static struct clk extal_clk = {
24 .name = "extal",
25 .id = -1,
26 .rate = 33333333,
37}; 27};
38 28
39static unsigned long module_clk_recalc(struct clk *clk) 29static unsigned long pll_recalc(struct clk *clk)
40{ 30{
41 int idx = (ctrl_inl(FRQMR1) & 0x000f); 31 int multiplier;
42 return clk->parent->rate / pfc_divisors[idx];
43}
44 32
45static struct clk_ops sh7786_module_clk_ops = { 33 /*
46 .recalc = module_clk_recalc, 34 * Clock modes 0, 1, and 2 use an x64 multiplier against PLL1,
47}; 35 * while modes 3, 4, and 5 use an x32.
36 */
37 multiplier = (sh_mv.mv_mode_pins() & 0xf) < 3 ? 64 : 32;
48 38
49static unsigned long bus_clk_recalc(struct clk *clk) 39 return clk->parent->rate * multiplier;
50{
51 int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
52 return clk->parent->rate / bfc_divisors[idx];
53} 40}
54 41
55static struct clk_ops sh7786_bus_clk_ops = { 42static struct clk_ops pll_clk_ops = {
56 .recalc = bus_clk_recalc, 43 .recalc = pll_recalc,
57}; 44};
58 45
59static unsigned long cpu_clk_recalc(struct clk *clk) 46static struct clk pll_clk = {
60{ 47 .name = "pll_clk",
61 int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003); 48 .id = -1,
62 return clk->parent->rate / ifc_divisors[idx]; 49 .ops = &pll_clk_ops,
63} 50 .parent = &extal_clk,
64 51 .flags = CLK_ENABLE_ON_INIT,
65static struct clk_ops sh7786_cpu_clk_ops = {
66 .recalc = cpu_clk_recalc,
67}; 52};
68 53
69static struct clk_ops *sh7786_clk_ops[] = { 54static struct clk *clks[] = {
70 &sh7786_master_clk_ops, 55 &extal_clk,
71 &sh7786_module_clk_ops, 56 &pll_clk,
72 &sh7786_bus_clk_ops,
73 &sh7786_cpu_clk_ops,
74}; 57};
75 58
76void __init arch_init_clk_ops(struct clk_ops **ops, int idx) 59static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
77{ 60 24, 32, 36, 48 };
78 if (idx < ARRAY_SIZE(sh7786_clk_ops))
79 *ops = sh7786_clk_ops[idx];
80}
81
82static unsigned long shyway_clk_recalc(struct clk *clk)
83{
84 int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
85 return clk->parent->rate / sfc_divisors[idx];
86}
87 61
88static struct clk_ops sh7786_shyway_clk_ops = { 62static struct clk_div_mult_table div4_table = {
89 .recalc = shyway_clk_recalc, 63 .divisors = div2,
64 .nr_divisors = ARRAY_SIZE(div2),
90}; 65};
91 66
92static struct clk sh7786_shyway_clk = { 67enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR };
93 .name = "shyway_clk",
94 .flags = CLK_ENABLE_ON_INIT,
95 .ops = &sh7786_shyway_clk_ops,
96};
97 68
98static unsigned long ddr_clk_recalc(struct clk *clk) 69#define DIV4(_str, _bit, _mask, _flags) \
99{ 70 SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags)
100 int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
101 return clk->parent->rate / mfc_divisors[idx];
102}
103 71
104static struct clk_ops sh7786_ddr_clk_ops = { 72struct clk div4_clks[DIV4_NR] = {
105 .recalc = ddr_clk_recalc, 73 [DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0),
74 [DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0),
75 [DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT),
76 [DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT),
77 [DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT),
78 [DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT),
106}; 79};
107 80
108static struct clk sh7786_ddr_clk = { 81#define MSTPCR0 0xffc40030
109 .name = "ddr_clk", 82#define MSTPCR1 0xffc40034
110 .flags = CLK_ENABLE_ON_INIT, 83
111 .ops = &sh7786_ddr_clk_ops, 84static struct clk mstp_clks[] = {
112}; 85 /* MSTPCR0 */
113 86 SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0),
114/* 87 SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0),
115 * Additional SH7786-specific on-chip clocks that aren't already part of the 88 SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0),
116 * clock framework 89 SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0),
117 */ 90 SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0),
118static struct clk *sh7786_onchip_clocks[] = { 91 SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0),
119 &sh7786_shyway_clk, 92 SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0),
120 &sh7786_ddr_clk, 93 SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0),
94 SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0),
95 SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0),
96 SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0),
97 SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0),
98 SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0),
99 SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0),
100 SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0),
101 SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0),
102 SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0),
103 SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0),
104 SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0),
105 SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0),
106 SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0),
107
108 /* MSTPCR1 */
109 SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0),
110 SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0),
111 SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0),
112 SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0),
113 SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0),
114 SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0),
115 SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0),
116 SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0),
121}; 117};
122 118
123int __init arch_clk_init(void) 119int __init arch_clk_init(void)
124{ 120{
125 struct clk *clk;
126 int i, ret = 0; 121 int i, ret = 0;
127 122
128 cpg_clk_init(); 123 for (i = 0; i < ARRAY_SIZE(clks); i++)
129 124 ret |= clk_register(clks[i]);
130 clk = clk_get(NULL, "master_clk");
131 for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) {
132 struct clk *clkp = sh7786_onchip_clocks[i];
133
134 clkp->parent = clk;
135 ret |= clk_register(clkp);
136 }
137 125
138 clk_put(clk); 126 if (!ret)
127 ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
128 &div4_table);
129 if (!ret)
130 ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
139 131
140 return ret; 132 return ret;
141} 133}