blob: aa3444b41e72a2afe89815fa9fda8a1bf4806a97 [file] [log] [blame]
Kuninori Morimotoadd5ca22018-12-28 00:32:11 -08001// SPDX-License-Identifier: GPL-2.0
Magnus Damm4ed37392009-06-04 07:35:25 +00002/*
3 * arch/sh/kernel/cpu/sh4a/clock-sh7366.c
4 *
5 * SH7366 clock framework support
6 *
7 * Copyright (C) 2009 Magnus Damm
Magnus Damm4ed37392009-06-04 07:35:25 +00008 */
9#include <linux/init.h>
10#include <linux/kernel.h>
11#include <linux/io.h>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010012#include <linux/clkdev.h>
Magnus Damm4ed37392009-06-04 07:35:25 +000013#include <asm/clock.h>
14
15/* SH7366 registers */
16#define FRQCR 0xa4150000
17#define VCLKCR 0xa4150004
18#define SCLKACR 0xa4150008
19#define SCLKBCR 0xa415000c
20#define PLLCR 0xa4150024
21#define MSTPCR0 0xa4150030
22#define MSTPCR1 0xa4150034
23#define MSTPCR2 0xa4150038
24#define DLLFRQ 0xa4150050
25
26/* Fixed 32 KHz root clock for RTC and Power Management purposes */
27static struct clk r_clk = {
Magnus Damm4ed37392009-06-04 07:35:25 +000028 .rate = 32768,
29};
30
31/*
32 * Default rate for the root input clock, reset this with clk_set_rate()
33 * from the platform code.
34 */
35struct clk extal_clk = {
Magnus Damm4ed37392009-06-04 07:35:25 +000036 .rate = 33333333,
37};
38
39/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
40static unsigned long dll_recalc(struct clk *clk)
41{
42 unsigned long mult;
43
44 if (__raw_readl(PLLCR) & 0x1000)
45 mult = __raw_readl(DLLFRQ);
46 else
47 mult = 0;
48
49 return clk->parent->rate * mult;
50}
51
Magnus Damm33cb61a2012-02-29 22:17:55 +090052static struct sh_clk_ops dll_clk_ops = {
Magnus Damm4ed37392009-06-04 07:35:25 +000053 .recalc = dll_recalc,
54};
55
56static struct clk dll_clk = {
Magnus Damm4ed37392009-06-04 07:35:25 +000057 .ops = &dll_clk_ops,
58 .parent = &r_clk,
59 .flags = CLK_ENABLE_ON_INIT,
60};
61
62static unsigned long pll_recalc(struct clk *clk)
63{
64 unsigned long mult = 1;
65 unsigned long div = 1;
66
67 if (__raw_readl(PLLCR) & 0x4000)
68 mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
69 else
70 div = 2;
71
72 return (clk->parent->rate * mult) / div;
73}
74
Magnus Damm33cb61a2012-02-29 22:17:55 +090075static struct sh_clk_ops pll_clk_ops = {
Magnus Damm4ed37392009-06-04 07:35:25 +000076 .recalc = pll_recalc,
77};
78
79static struct clk pll_clk = {
Magnus Damm4ed37392009-06-04 07:35:25 +000080 .ops = &pll_clk_ops,
81 .flags = CLK_ENABLE_ON_INIT,
82};
83
84struct clk *main_clks[] = {
85 &r_clk,
86 &extal_clk,
87 &dll_clk,
88 &pll_clk,
89};
90
91static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
92static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
93
Magnus Damm0a5f3372010-02-19 09:22:25 +000094static struct clk_div_mult_table div4_div_mult_table = {
Magnus Damm4ed37392009-06-04 07:35:25 +000095 .divisors = divisors,
96 .nr_divisors = ARRAY_SIZE(divisors),
97 .multipliers = multipliers,
98 .nr_multipliers = ARRAY_SIZE(multipliers),
99};
100
Magnus Damm0a5f3372010-02-19 09:22:25 +0000101static struct clk_div4_table div4_table = {
102 .div_mult_table = &div4_div_mult_table,
103};
104
Magnus Damm4ed37392009-06-04 07:35:25 +0000105enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
106 DIV4_SIUA, DIV4_SIUB, DIV4_NR };
107
Magnus Damm914ebf02010-05-11 07:06:13 +0000108#define DIV4(_reg, _bit, _mask, _flags) \
109 SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
Magnus Damm4ed37392009-06-04 07:35:25 +0000110
111struct clk div4_clks[DIV4_NR] = {
Magnus Damm914ebf02010-05-11 07:06:13 +0000112 [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
113 [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
114 [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
115 [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
116 [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
117 [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
118 [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
119 [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
Magnus Damm4ed37392009-06-04 07:35:25 +0000120};
121
Magnus Damm098ec492010-05-10 14:01:55 +0000122enum { DIV6_V, DIV6_NR };
123
124struct clk div6_clks[DIV6_NR] = {
Magnus Damm9e1985e2010-05-10 14:02:09 +0000125 [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
Magnus Damm4ed37392009-06-04 07:35:25 +0000126};
127
Magnus Dammc77a9c32010-05-11 05:00:47 +0000128#define MSTP(_parent, _reg, _bit, _flags) \
129 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
Magnus Damm4ed37392009-06-04 07:35:25 +0000130
Magnus Damm47806832010-05-11 04:59:58 +0000131enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
132 MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
133 MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
134 MSTP007, MSTP006, MSTP005, MSTP002, MSTP001,
135 MSTP109, MSTP100,
136 MSTP227, MSTP226, MSTP224, MSTP223, MSTP222, MSTP218, MSTP217,
137 MSTP211, MSTP207, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
138 MSTP_NR };
139
140static struct clk mstp_clks[MSTP_NR] = {
Magnus Damm4ed37392009-06-04 07:35:25 +0000141 /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
Magnus Dammc77a9c32010-05-11 05:00:47 +0000142 [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
143 [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
144 [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
145 [MSTP028] = MSTP(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
146 [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
147 [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
148 [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
149 [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
150 [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
151 [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
152 [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
153 [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
154 [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
155 [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
156 [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
157 [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
158 [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
159 [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
160 [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
161 [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
162 [MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
Magnus Damm4ed37392009-06-04 07:35:25 +0000163
Magnus Dammc77a9c32010-05-11 05:00:47 +0000164 [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
Magnus Damm4ed37392009-06-04 07:35:25 +0000165
Magnus Dammc77a9c32010-05-11 05:00:47 +0000166 [MSTP227] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 27, 0),
167 [MSTP226] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 26, 0),
168 [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
169 [MSTP223] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 23, 0),
170 [MSTP222] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 22, 0),
171 [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
172 [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
173 [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
174 [MSTP207] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
175 [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
176 [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
177 [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
178 [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
179 [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
180 [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
Magnus Damm4ed37392009-06-04 07:35:25 +0000181};
182
Magnus Damm098ec492010-05-10 14:01:55 +0000183static struct clk_lookup lookups[] = {
Magnus Damm59aa69d2010-05-11 09:35:55 +0000184 /* main clocks */
185 CLKDEV_CON_ID("rclk", &r_clk),
186 CLKDEV_CON_ID("extal", &extal_clk),
187 CLKDEV_CON_ID("dll_clk", &dll_clk),
188 CLKDEV_CON_ID("pll_clk", &pll_clk),
189
Magnus Damm40956e72010-05-11 07:05:50 +0000190 /* DIV4 clocks */
191 CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
192 CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
193 CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
194 CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
195 CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
196 CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
197 CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
198 CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
199
Magnus Damm098ec492010-05-10 14:01:55 +0000200 /* DIV6 clocks */
201 CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
Magnus Dammb87cece2010-05-11 05:00:06 +0000202
203 /* MSTP32 clocks */
204 CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
205 CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
206 CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
207 CLKDEV_CON_ID("rsmem0", &mstp_clks[MSTP028]),
208 CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
209 CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
210 CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
211 CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
212 CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
213 CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
214 CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
215 CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
Laurent Pinchart9b17e482014-04-23 13:15:08 +0200216 CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[MSTP014]),
Magnus Dammb87cece2010-05-11 05:00:06 +0000217 CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
218 CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
219 CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
Kuninori Morimotoee0c2ef2011-07-06 01:18:19 +0000220
Laurent Pinchartfa3d39bf2015-09-14 15:14:24 +0300221 CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
222 CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
223 CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
Kuninori Morimotoee0c2ef2011-07-06 01:18:19 +0000224
Magnus Dammb87cece2010-05-11 05:00:06 +0000225 CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
226 CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
Kuninori Morimoto54f7c112011-07-05 09:38:21 +0000227 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
Magnus Dammb87cece2010-05-11 05:00:06 +0000228 CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]),
229 CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]),
230 CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]),
231 CLKDEV_CON_ID("dacy0", &mstp_clks[MSTP223]),
232 CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP222]),
233 CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
234 CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
235 CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
236 CLKDEV_CON_ID("veu1", &mstp_clks[MSTP207]),
237 CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
238 CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
239 CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
240 CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
241 CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
242 CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
Magnus Damm098ec492010-05-10 14:01:55 +0000243};
244
Magnus Damm4ed37392009-06-04 07:35:25 +0000245int __init arch_clk_init(void)
246{
247 int k, ret = 0;
248
249 /* autodetect extal or dll configuration */
250 if (__raw_readl(PLLCR) & 0x1000)
251 pll_clk.parent = &dll_clk;
252 else
253 pll_clk.parent = &extal_clk;
254
255 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
256 ret = clk_register(main_clks[k]);
257
Magnus Damm098ec492010-05-10 14:01:55 +0000258 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
259
Magnus Damm4ed37392009-06-04 07:35:25 +0000260 if (!ret)
261 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
262
263 if (!ret)
Magnus Damm098ec492010-05-10 14:01:55 +0000264 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
Magnus Damm4ed37392009-06-04 07:35:25 +0000265
266 if (!ret)
Nobuhiro Iwamatsuad3337c2012-06-27 09:59:40 +0900267 ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
Magnus Damm4ed37392009-06-04 07:35:25 +0000268
269 return ret;
270}