Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
26498 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* arch/sh/kernel/cpu/sh4a/clock-sh7343.c
4
*
5
* SH7343 clock framework support
6
*
7
* Copyright (C) 2009 Magnus Damm
8
*/
9
#include <linux/init.h>
10
#include <linux/kernel.h>
11
#include <linux/io.h>
12
#include <linux/clkdev.h>
13
#include <asm/clock.h>
14
15
/* SH7343 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 */
27
static struct clk r_clk = {
28
.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
*/
35
struct clk extal_clk = {
36
.rate = 33333333,
37
};
38
39
/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
40
static 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
52
static struct sh_clk_ops dll_clk_ops = {
53
.recalc = dll_recalc,
54
};
55
56
static struct clk dll_clk = {
57
.ops = &dll_clk_ops,
58
.parent = &r_clk,
59
.flags = CLK_ENABLE_ON_INIT,
60
};
61
62
static unsigned long pll_recalc(struct clk *clk)
63
{
64
unsigned long mult = 1;
65
66
if (__raw_readl(PLLCR) & 0x4000)
67
mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
68
69
return clk->parent->rate * mult;
70
}
71
72
static struct sh_clk_ops pll_clk_ops = {
73
.recalc = pll_recalc,
74
};
75
76
static struct clk pll_clk = {
77
.ops = &pll_clk_ops,
78
.flags = CLK_ENABLE_ON_INIT,
79
};
80
81
struct clk *main_clks[] = {
82
&r_clk,
83
&extal_clk,
84
&dll_clk,
85
&pll_clk,
86
};
87
88
static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
89
static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
90
91
static struct clk_div_mult_table div4_div_mult_table = {
92
.divisors = divisors,
93
.nr_divisors = ARRAY_SIZE(divisors),
94
.multipliers = multipliers,
95
.nr_multipliers = ARRAY_SIZE(multipliers),
96
};
97
98
static struct clk_div4_table div4_table = {
99
.div_mult_table = &div4_div_mult_table,
100
};
101
102
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
103
DIV4_SIUA, DIV4_SIUB, DIV4_NR };
104
105
#define DIV4(_reg, _bit, _mask, _flags) \
106
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
107
108
struct clk div4_clks[DIV4_NR] = {
109
[DIV4_I] = DIV4(FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT),
110
[DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
111
[DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
112
[DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
113
[DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
114
[DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
115
[DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
116
[DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
117
};
118
119
enum { DIV6_V, DIV6_NR };
120
121
struct clk div6_clks[DIV6_NR] = {
122
[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
123
};
124
125
#define MSTP(_parent, _reg, _bit, _flags) \
126
SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
127
128
enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
129
MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
130
MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
131
MSTP007, MSTP006, MSTP005, MSTP004, MSTP003, MSTP002, MSTP001,
132
MSTP109, MSTP108, MSTP100,
133
MSTP225, MSTP224, MSTP218, MSTP217, MSTP216,
134
MSTP214, MSTP213, MSTP212, MSTP211, MSTP208,
135
MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
136
MSTP_NR };
137
138
static struct clk mstp_clks[MSTP_NR] = {
139
[MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
140
[MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
141
[MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
142
[MSTP028] = MSTP(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
143
[MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
144
[MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
145
[MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
146
[MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
147
[MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
148
[MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
149
[MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
150
[MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
151
[MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
152
[MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
153
[MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
154
[MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
155
[MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
156
[MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
157
[MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
158
[MSTP004] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
159
[MSTP003] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
160
[MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
161
[MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
162
163
[MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
164
[MSTP108] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
165
166
[MSTP225] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 25, 0),
167
[MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
168
[MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
169
[MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
170
[MSTP216] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 16, 0),
171
[MSTP214] = MSTP(&r_clk, MSTPCR2, 14, 0),
172
[MSTP213] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 13, 0),
173
[MSTP212] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 12, 0),
174
[MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
175
[MSTP208] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 8, 0),
176
[MSTP206] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
177
[MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
178
[MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
179
[MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
180
[MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
181
[MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
182
[MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
183
};
184
185
static struct clk_lookup lookups[] = {
186
/* main clocks */
187
CLKDEV_CON_ID("rclk", &r_clk),
188
CLKDEV_CON_ID("extal", &extal_clk),
189
CLKDEV_CON_ID("dll_clk", &dll_clk),
190
CLKDEV_CON_ID("pll_clk", &pll_clk),
191
192
/* DIV4 clocks */
193
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
194
CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
195
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
196
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
197
CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
198
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
199
CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
200
CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
201
202
/* DIV6 clocks */
203
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
204
205
/* MSTP32 clocks */
206
CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
207
CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
208
CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
209
CLKDEV_CON_ID("uram0", &mstp_clks[MSTP028]),
210
CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
211
CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
212
CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
213
CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
214
CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
215
CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
216
CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
217
CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
218
CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[MSTP014]),
219
CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
220
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
221
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
222
223
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
224
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
225
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
226
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP004]),
227
228
CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
229
CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),
230
CLKDEV_CON_ID("siof1", &mstp_clks[MSTP001]),
231
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
232
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP108]),
233
CLKDEV_CON_ID("tpu0", &mstp_clks[MSTP225]),
234
CLKDEV_CON_ID("irda0", &mstp_clks[MSTP224]),
235
CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
236
CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
237
CLKDEV_CON_ID("sim0", &mstp_clks[MSTP216]),
238
CLKDEV_CON_ID("keysc0", &mstp_clks[MSTP214]),
239
CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP213]),
240
CLKDEV_CON_ID("s3d40", &mstp_clks[MSTP212]),
241
CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
242
CLKDEV_CON_ID("siu0", &mstp_clks[MSTP208]),
243
CLKDEV_CON_ID("jpu0", &mstp_clks[MSTP206]),
244
CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
245
CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
246
CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
247
CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
248
CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
249
CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
250
};
251
252
int __init arch_clk_init(void)
253
{
254
int k, ret = 0;
255
256
/* autodetect extal or dll configuration */
257
if (__raw_readl(PLLCR) & 0x1000)
258
pll_clk.parent = &dll_clk;
259
else
260
pll_clk.parent = &extal_clk;
261
262
for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
263
ret = clk_register(main_clks[k]);
264
265
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
266
267
if (!ret)
268
ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
269
270
if (!ret)
271
ret = sh_clk_div6_register(div6_clks, DIV6_NR);
272
273
if (!ret)
274
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
275
276
return ret;
277
}
278
279