Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
26498 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* arch/sh/kernel/cpu/sh4a/clock-sh7366.c
4
*
5
* SH7366 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
/* 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 */
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
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
75
static struct sh_clk_ops pll_clk_ops = {
76
.recalc = pll_recalc,
77
};
78
79
static struct clk pll_clk = {
80
.ops = &pll_clk_ops,
81
.flags = CLK_ENABLE_ON_INIT,
82
};
83
84
struct clk *main_clks[] = {
85
&r_clk,
86
&extal_clk,
87
&dll_clk,
88
&pll_clk,
89
};
90
91
static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
92
static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
93
94
static struct clk_div_mult_table div4_div_mult_table = {
95
.divisors = divisors,
96
.nr_divisors = ARRAY_SIZE(divisors),
97
.multipliers = multipliers,
98
.nr_multipliers = ARRAY_SIZE(multipliers),
99
};
100
101
static struct clk_div4_table div4_table = {
102
.div_mult_table = &div4_div_mult_table,
103
};
104
105
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
106
DIV4_SIUA, DIV4_SIUB, DIV4_NR };
107
108
#define DIV4(_reg, _bit, _mask, _flags) \
109
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
110
111
struct clk div4_clks[DIV4_NR] = {
112
[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),
120
};
121
122
enum { DIV6_V, DIV6_NR };
123
124
struct clk div6_clks[DIV6_NR] = {
125
[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
126
};
127
128
#define MSTP(_parent, _reg, _bit, _flags) \
129
SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
130
131
enum { 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
140
static struct clk mstp_clks[MSTP_NR] = {
141
/* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
142
[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),
163
164
[MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
165
166
[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),
181
};
182
183
static struct clk_lookup lookups[] = {
184
/* 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
190
/* 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
200
/* DIV6 clocks */
201
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
202
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]),
216
CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[MSTP014]),
217
CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
218
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
219
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
220
221
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]),
224
225
CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
226
CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
227
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
228
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]),
243
};
244
245
int __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
258
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
259
260
if (!ret)
261
ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
262
263
if (!ret)
264
ret = sh_clk_div6_register(div6_clks, DIV6_NR);
265
266
if (!ret)
267
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
268
269
return ret;
270
}
271
272