Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/aspeed/clk-ast2700.c
121817 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (c) 2024 ASPEED Technology Inc.
4
* Author: Ryan Chen <[email protected]>
5
*/
6
#include <linux/auxiliary_bus.h>
7
#include <linux/bitfield.h>
8
#include <linux/clk-provider.h>
9
#include <linux/io.h>
10
#include <linux/mod_devicetable.h>
11
#include <linux/platform_device.h>
12
#include <linux/slab.h>
13
#include <linux/units.h>
14
15
#include <dt-bindings/clock/aspeed,ast2700-scu.h>
16
17
/* SOC0 */
18
#define SCU0_HWSTRAP1 0x010
19
#define SCU0_CLK_STOP 0x240
20
#define SCU0_CLK_SEL1 0x280
21
#define SCU0_CLK_SEL2 0x284
22
#define GET_USB_REFCLK_DIV(x) ((GENMASK(23, 20) & (x)) >> 20)
23
#define UART_DIV13_EN BIT(30)
24
#define SCU0_HPLL_PARAM 0x300
25
#define SCU0_DPLL_PARAM 0x308
26
#define SCU0_MPLL_PARAM 0x310
27
#define SCU0_D0CLK_PARAM 0x320
28
#define SCU0_D1CLK_PARAM 0x330
29
#define SCU0_CRT0CLK_PARAM 0x340
30
#define SCU0_CRT1CLK_PARAM 0x350
31
#define SCU0_MPHYCLK_PARAM 0x360
32
33
/* SOC1 */
34
#define SCU1_REVISION_ID 0x0
35
#define REVISION_ID GENMASK(23, 16)
36
#define SCU1_CLK_STOP 0x240
37
#define SCU1_CLK_STOP2 0x260
38
#define SCU1_CLK_SEL1 0x280
39
#define SCU1_CLK_SEL2 0x284
40
#define SCU1_CLK_I3C_DIV_MASK GENMASK(25, 23)
41
#define SCU1_CLK_I3C_DIV(n) ((n) - 1)
42
#define UXCLK_MASK GENMASK(1, 0)
43
#define HUXCLK_MASK GENMASK(4, 3)
44
#define SCU1_HPLL_PARAM 0x300
45
#define SCU1_APLL_PARAM 0x310
46
#define SCU1_DPLL_PARAM 0x320
47
#define SCU1_UXCLK_CTRL 0x330
48
#define SCU1_HUXCLK_CTRL 0x334
49
#define SCU1_MAC12_CLK_DLY 0x390
50
#define SCU1_MAC12_CLK_DLY_100M 0x394
51
#define SCU1_MAC12_CLK_DLY_10M 0x398
52
53
enum ast2700_clk_type {
54
CLK_MUX,
55
CLK_PLL,
56
CLK_HPLL,
57
CLK_GATE,
58
CLK_MISC,
59
CLK_FIXED,
60
CLK_DIVIDER,
61
CLK_UART_PLL,
62
CLK_GATE_ASPEED,
63
CLK_FIXED_FACTOR,
64
CLK_FIXED_DISPLAY,
65
};
66
67
struct ast2700_clk_fixed_factor_data {
68
unsigned int mult;
69
unsigned int div;
70
int parent_id;
71
};
72
73
struct ast2700_clk_gate_data {
74
int parent_id;
75
u32 flags;
76
u32 reg;
77
u8 bit;
78
};
79
80
struct ast2700_clk_mux_data {
81
const struct clk_hw **parent_hws;
82
const unsigned int *parent_ids;
83
unsigned int num_parents;
84
u8 bit_shift;
85
u8 bit_width;
86
u32 reg;
87
};
88
89
struct ast2700_clk_div_data {
90
const struct clk_div_table *div_table;
91
unsigned int parent_id;
92
u8 bit_shift;
93
u8 bit_width;
94
u32 reg;
95
};
96
97
struct ast2700_clk_pll_data {
98
unsigned int parent_id;
99
u32 reg;
100
};
101
102
struct ast2700_clk_fixed_rate_data {
103
unsigned long fixed_rate;
104
};
105
106
struct ast2700_clk_display_fixed_data {
107
u32 reg;
108
};
109
110
struct ast2700_clk_info {
111
const char *name;
112
u32 id;
113
u32 reg;
114
u32 type;
115
union {
116
struct ast2700_clk_fixed_factor_data factor;
117
struct ast2700_clk_fixed_rate_data rate;
118
struct ast2700_clk_display_fixed_data display_rate;
119
struct ast2700_clk_gate_data gate;
120
struct ast2700_clk_div_data div;
121
struct ast2700_clk_pll_data pll;
122
struct ast2700_clk_mux_data mux;
123
} data;
124
};
125
126
struct ast2700_clk_data {
127
const struct ast2700_clk_info *clk_info;
128
unsigned int nr_clks;
129
const int scu;
130
};
131
132
struct ast2700_clk_ctrl {
133
const struct ast2700_clk_data *clk_data;
134
struct device *dev;
135
void __iomem *base;
136
spinlock_t lock; /* clk lock */
137
};
138
139
static const struct clk_div_table ast2700_rgmii_div_table[] = {
140
{ 0x0, 4 },
141
{ 0x1, 4 },
142
{ 0x2, 6 },
143
{ 0x3, 8 },
144
{ 0x4, 10 },
145
{ 0x5, 12 },
146
{ 0x6, 14 },
147
{ 0x7, 16 },
148
{ 0 }
149
};
150
151
static const struct clk_div_table ast2700_rmii_div_table[] = {
152
{ 0x0, 8 },
153
{ 0x1, 8 },
154
{ 0x2, 12 },
155
{ 0x3, 16 },
156
{ 0x4, 20 },
157
{ 0x5, 24 },
158
{ 0x6, 28 },
159
{ 0x7, 32 },
160
{ 0 }
161
};
162
163
static const struct clk_div_table ast2700_clk_div_table[] = {
164
{ 0x0, 2 },
165
{ 0x1, 2 },
166
{ 0x2, 3 },
167
{ 0x3, 4 },
168
{ 0x4, 5 },
169
{ 0x5, 6 },
170
{ 0x6, 7 },
171
{ 0x7, 8 },
172
{ 0 }
173
};
174
175
static const struct clk_div_table ast2700_clk_div_table2[] = {
176
{ 0x0, 2 },
177
{ 0x1, 4 },
178
{ 0x2, 6 },
179
{ 0x3, 8 },
180
{ 0x4, 10 },
181
{ 0x5, 12 },
182
{ 0x6, 14 },
183
{ 0x7, 16 },
184
{ 0 }
185
};
186
187
static const struct clk_div_table ast2700_hclk_div_table[] = {
188
{ 0x0, 6 },
189
{ 0x1, 5 },
190
{ 0x2, 4 },
191
{ 0x3, 7 },
192
{ 0 }
193
};
194
195
static const struct clk_div_table ast2700_clk_uart_div_table[] = {
196
{ 0x0, 1 },
197
{ 0x1, 13 },
198
{ 0 }
199
};
200
201
/* soc 0 */
202
static const unsigned int psp_parent_ids[] = {
203
SCU0_CLK_MPLL,
204
SCU0_CLK_HPLL,
205
SCU0_CLK_HPLL,
206
SCU0_CLK_HPLL,
207
SCU0_CLK_MPLL_DIV2,
208
SCU0_CLK_HPLL_DIV2,
209
SCU0_CLK_HPLL,
210
SCU0_CLK_HPLL
211
};
212
213
static const struct clk_hw *psp_parent_hws[ARRAY_SIZE(psp_parent_ids)];
214
215
static const unsigned int hclk_parent_ids[] = {
216
SCU0_CLK_HPLL,
217
SCU0_CLK_MPLL
218
};
219
220
static const struct clk_hw *hclk_parent_hws[ARRAY_SIZE(hclk_parent_ids)];
221
222
static const unsigned int emmc_parent_ids[] = {
223
SCU0_CLK_MPLL_DIV4,
224
SCU0_CLK_HPLL_DIV4
225
};
226
227
static const struct clk_hw *emmc_parent_hws[ARRAY_SIZE(emmc_parent_ids)];
228
229
static const unsigned int mphy_parent_ids[] = {
230
SCU0_CLK_MPLL,
231
SCU0_CLK_HPLL,
232
SCU0_CLK_DPLL,
233
SCU0_CLK_192M
234
};
235
236
static const struct clk_hw *mphy_parent_hws[ARRAY_SIZE(mphy_parent_ids)];
237
238
static const unsigned int u2phy_parent_ids[] = {
239
SCU0_CLK_MPLL,
240
SCU0_CLK_HPLL
241
};
242
243
static const struct clk_hw *u2phy_parent_hws[ARRAY_SIZE(u2phy_parent_ids)];
244
245
static const unsigned int uart_parent_ids[] = {
246
SCU0_CLK_24M,
247
SCU0_CLK_192M
248
};
249
250
static const struct clk_hw *uart_parent_hws[ARRAY_SIZE(uart_parent_ids)];
251
252
/* soc 1 */
253
static const unsigned int uartx_parent_ids[] = {
254
SCU1_CLK_UARTX,
255
SCU1_CLK_HUARTX
256
};
257
258
static const struct clk_hw *uartx_parent_hws[ARRAY_SIZE(uartx_parent_ids)];
259
260
static const unsigned int uxclk_parent_ids[] = {
261
SCU1_CLK_APLL_DIV4,
262
SCU1_CLK_APLL_DIV2,
263
SCU1_CLK_APLL,
264
SCU1_CLK_HPLL
265
};
266
267
static const struct clk_hw *uxclk_parent_hws[ARRAY_SIZE(uxclk_parent_ids)];
268
269
static const unsigned int sdclk_parent_ids[] = {
270
SCU1_CLK_HPLL,
271
SCU1_CLK_APLL
272
};
273
274
static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)];
275
276
#define FIXED_CLK(_id, _name, _rate) \
277
{ \
278
.id = _id, \
279
.type = CLK_FIXED, \
280
.name = _name, \
281
.data = { .rate = { .fixed_rate = _rate, } }, \
282
}
283
284
#define FIXED_DISPLAY_CLK(_id, _name, _reg) \
285
{ \
286
.id = _id, \
287
.type = CLK_FIXED_DISPLAY, \
288
.name = _name, \
289
.data = { .display_rate = { .reg = _reg } }, \
290
}
291
292
#define PLL_CLK(_id, _type, _name, _parent_id, _reg) \
293
{ \
294
.id = _id, \
295
.type = _type, \
296
.name = _name, \
297
.data = { .pll = { \
298
.parent_id = _parent_id, \
299
.reg = _reg, \
300
} }, \
301
}
302
303
#define MUX_CLK(_id, _name, _parent_ids, _num_parents, _parent_hws, _reg, _shift, _width) \
304
{ \
305
.id = _id, \
306
.type = CLK_MUX, \
307
.name = _name, \
308
.data = { \
309
.mux = { \
310
.parent_ids = _parent_ids, \
311
.parent_hws = _parent_hws, \
312
.num_parents = _num_parents, \
313
.reg = (_reg), \
314
.bit_shift = _shift, \
315
.bit_width = _width, \
316
}, \
317
}, \
318
}
319
320
#define DIVIDER_CLK(_id, _name, _parent_id, _reg, _shift, _width, _div_table) \
321
{ \
322
.id = _id, \
323
.type = CLK_DIVIDER, \
324
.name = _name, \
325
.data = { \
326
.div = { \
327
.parent_id = _parent_id, \
328
.reg = _reg, \
329
.bit_shift = _shift, \
330
.bit_width = _width, \
331
.div_table = _div_table, \
332
}, \
333
}, \
334
}
335
336
#define FIXED_FACTOR_CLK(_id, _name, _parent_id, _mult, _div) \
337
{ \
338
.id = _id, \
339
.type = CLK_FIXED_FACTOR, \
340
.name = _name, \
341
.data = { .factor = { .parent_id = _parent_id, .mult = _mult, .div = _div, } }, \
342
}
343
344
#define GATE_CLK(_id, _type, _name, _parent_id, _reg, _bit, _flags) \
345
{ \
346
.id = _id, \
347
.type = _type, \
348
.name = _name, \
349
.data = { \
350
.gate = { \
351
.parent_id = _parent_id, \
352
.reg = _reg, \
353
.bit = _bit, \
354
.flags = _flags, \
355
}, \
356
}, \
357
}
358
359
static const struct ast2700_clk_info ast2700_scu0_clk_info[] __initconst = {
360
FIXED_CLK(SCU0_CLKIN, "soc0-clkin", 25 * HZ_PER_MHZ),
361
FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", 24 * HZ_PER_MHZ),
362
FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", 192 * HZ_PER_MHZ),
363
FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", 12 * HZ_PER_MHZ),
364
FIXED_DISPLAY_CLK(SCU0_CLK_D0, "d0clk", SCU0_D0CLK_PARAM),
365
FIXED_DISPLAY_CLK(SCU0_CLK_D1, "d1clk", SCU0_D1CLK_PARAM),
366
FIXED_DISPLAY_CLK(SCU0_CLK_CRT0, "crt0clk", SCU0_CRT0CLK_PARAM),
367
FIXED_DISPLAY_CLK(SCU0_CLK_CRT1, "crt1clk", SCU0_CRT1CLK_PARAM),
368
PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", SCU0_CLKIN, SCU0_HPLL_PARAM),
369
PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", SCU0_CLKIN, SCU0_DPLL_PARAM),
370
PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", SCU0_CLKIN, SCU0_MPLL_PARAM),
371
FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", SCU0_CLK_HPLL, 1, 2),
372
FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", SCU0_CLK_HPLL, 1, 4),
373
FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", SCU0_CLK_MPLL, 1, 2),
374
FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", SCU0_CLK_MPLL, 1, 4),
375
FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", SCU0_CLK_MPLL, 1, 8),
376
FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", SCU0_CLK_MPLL, 1, 4),
377
MUX_CLK(SCU0_CLK_PSP, "pspclk", psp_parent_ids, ARRAY_SIZE(psp_parent_ids),
378
psp_parent_hws, SCU0_HWSTRAP1, 2, 3),
379
FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", SCU0_CLK_PSP, 1, 2),
380
MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", hclk_parent_ids, ARRAY_SIZE(hclk_parent_ids),
381
hclk_parent_hws, SCU0_HWSTRAP1, 7, 1),
382
MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_parent_ids, ARRAY_SIZE(emmc_parent_ids),
383
emmc_parent_hws, SCU0_CLK_SEL1, 11, 1),
384
MUX_CLK(SCU0_CLK_MPHYSRC, "mphysrc", mphy_parent_ids, ARRAY_SIZE(mphy_parent_ids),
385
mphy_parent_hws, SCU0_CLK_SEL2, 18, 2),
386
MUX_CLK(SCU0_CLK_U2PHY_REFCLKSRC, "u2phy_refclksrc", u2phy_parent_ids,
387
ARRAY_SIZE(u2phy_parent_ids), u2phy_parent_hws, SCU0_CLK_SEL2, 23, 1),
388
MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_parent_ids, ARRAY_SIZE(uart_parent_ids),
389
uart_parent_hws, SCU0_CLK_SEL2, 14, 1),
390
PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", SCU0_CLK_MPHYSRC, SCU0_MPHYCLK_PARAM),
391
PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", SCU0_CLK_U2PHY_REFCLKSRC,
392
SCU0_CLK_SEL2),
393
DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", SCU0_CLK_AHBMUX,
394
SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table),
395
DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", SCU0_CLK_EMMCMUX,
396
SCU0_CLK_SEL1, 12, 3, ast2700_clk_div_table2),
397
DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", SCU0_CLK_AXI0,
398
SCU0_CLK_SEL1, 23, 3, ast2700_clk_div_table2),
399
DIVIDER_CLK(SCU0_CLK_HPLL_DIV_AHB, "soc0-hpll-ahb", SCU0_CLK_HPLL,
400
SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table),
401
DIVIDER_CLK(SCU0_CLK_MPLL_DIV_AHB, "soc0-mpll-ahb", SCU0_CLK_MPLL,
402
SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table),
403
DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", SCU0_CLK_UART,
404
SCU0_CLK_SEL2, 30, 1, ast2700_clk_uart_div_table),
405
GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", SCU0_CLK_MPLL,
406
SCU0_CLK_STOP, 0, CLK_IS_CRITICAL),
407
GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", -1, SCU0_CLK_STOP, 1, 0),
408
GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", -1, SCU0_CLK_STOP, 2, 0),
409
GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", -1, SCU0_CLK_STOP, 3, 0),
410
GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", -1,
411
SCU0_CLK_STOP, 4, CLK_IS_CRITICAL),
412
GATE_CLK(SCU0_CLK_GATE_VGA0CLK, CLK_GATE_ASPEED, "vga0clk-gate", -1,
413
SCU0_CLK_STOP, 5, CLK_IS_CRITICAL),
414
GATE_CLK(SCU0_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc0-refclk-gate", SCU0_CLKIN,
415
SCU0_CLK_STOP, 6, CLK_IS_CRITICAL),
416
GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", -1,
417
SCU0_CLK_STOP, 7, 0),
418
GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", -1, SCU0_CLK_STOP, 9, 0),
419
GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", -1,
420
SCU0_CLK_STOP, 10, CLK_IS_CRITICAL),
421
GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", -1,
422
SCU0_CLK_STOP, 11, CLK_IS_CRITICAL),
423
GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", -1,
424
SCU0_CLK_STOP, 12, CLK_IS_CRITICAL),
425
GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", -1, SCU0_CLK_STOP, 13, 0),
426
GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", -1,
427
SCU0_CLK_STOP, 14, 0),
428
GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", SCU0_CLK_UART4,
429
SCU0_CLK_STOP, 15, CLK_IS_CRITICAL),
430
GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", -1,
431
SCU0_CLK_STOP, 16, CLK_IS_CRITICAL),
432
GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", -1,
433
SCU0_CLK_STOP, 17, CLK_IS_CRITICAL),
434
GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", -1,
435
SCU0_CLK_STOP, 18, CLK_IS_CRITICAL),
436
GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", -1,
437
SCU0_CLK_STOP, 19, CLK_IS_CRITICAL),
438
GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", -1,
439
SCU0_CLK_STOP, 20, 0),
440
GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", -1,
441
SCU0_CLK_STOP, 21, 0),
442
GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", -1,
443
SCU0_CLK_STOP, 23, 0),
444
GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", -1,
445
SCU0_CLK_STOP, 24, 0),
446
GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", -1,
447
SCU0_CLK_STOP, 25, 0),
448
GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", -1,
449
SCU0_CLK_STOP, 26, 0),
450
GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", SCU0_CLK_EMMC,
451
SCU0_CLK_STOP, 27, 0),
452
GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", -1,
453
SCU0_CLK_STOP, 28, 0),
454
};
455
456
static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
457
FIXED_CLK(SCU1_CLKIN, "soc1-clkin", 25 * HZ_PER_MHZ),
458
PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM),
459
PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM),
460
PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM),
461
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2),
462
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4),
463
FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10),
464
DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", SCU1_CLK_HPLL,
465
SCU1_CLK_SEL1, 18, 3, ast2700_clk_div_table2),
466
DIVIDER_CLK(SCU1_CLK_RMII, "rmii", SCU1_CLK_HPLL,
467
SCU1_CLK_SEL1, 21, 3, ast2700_rmii_div_table),
468
DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", SCU1_CLK_HPLL,
469
SCU1_CLK_SEL1, 25, 3, ast2700_rgmii_div_table),
470
DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", SCU1_CLK_HPLL,
471
SCU1_CLK_SEL1, 29, 3, ast2700_clk_div_table),
472
DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn",
473
SCU1_CLK_APLL, SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table),
474
DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", SCU1_CLK_HPLL,
475
SCU1_CLK_SEL2, 20, 3, ast2700_clk_div_table),
476
DIVIDER_CLK(SCU1_CLK_I3C, "soc1-i3c", SCU1_CLK_HPLL,
477
SCU1_CLK_SEL2, 23, 3, ast2700_clk_div_table),
478
MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdclk_parent_ids, ARRAY_SIZE(sdclk_parent_ids),
479
sdclk_parent_hws, SCU1_CLK_SEL1, 13, 1),
480
MUX_CLK(SCU1_CLK_UXCLK, "uxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
481
uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2),
482
MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
483
uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2),
484
DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX,
485
SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table),
486
PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL),
487
PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", SCU1_CLK_HUXCLK, SCU1_HUXCLK_CTRL),
488
MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
489
uartx_parent_hws, SCU1_CLK_SEL1, 0, 1),
490
MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
491
uartx_parent_hws, SCU1_CLK_SEL1, 1, 1),
492
MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
493
uartx_parent_hws, SCU1_CLK_SEL1, 2, 1),
494
MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
495
uartx_parent_hws, SCU1_CLK_SEL1, 3, 1),
496
MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
497
uartx_parent_hws, SCU1_CLK_SEL1, 5, 1),
498
MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
499
uartx_parent_hws, SCU1_CLK_SEL1, 6, 1),
500
MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
501
uartx_parent_hws, SCU1_CLK_SEL1, 7, 1),
502
MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
503
uartx_parent_hws, SCU1_CLK_SEL1, 8, 1),
504
MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
505
uartx_parent_hws, SCU1_CLK_SEL1, 9, 1),
506
MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
507
uartx_parent_hws, SCU1_CLK_SEL1, 10, 1),
508
MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
509
uartx_parent_hws, SCU1_CLK_SEL1, 11, 1),
510
MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
511
uartx_parent_hws, SCU1_CLK_SEL1, 12, 1),
512
FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", SCU1_CLK_HUARTX, 1, 1),
513
FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", SCU1_CLK_HUARTX, 1, 1),
514
GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", SCU1_CLK_RMII,
515
SCU1_MAC12_CLK_DLY, 29, 0),
516
GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", SCU1_CLK_RMII,
517
SCU1_MAC12_CLK_DLY, 30, 0),
518
GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", -1,
519
SCU1_CLK_STOP, 0, CLK_IS_CRITICAL),
520
GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", -1,
521
SCU1_CLK_STOP, 1, CLK_IS_CRITICAL),
522
GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", -1,
523
SCU1_CLK_STOP, 2, CLK_IS_CRITICAL),
524
GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", -1,
525
SCU1_CLK_STOP, 3, CLK_IS_CRITICAL),
526
GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", SCU1_CLK_SDCLK,
527
SCU1_CLK_STOP, 4, CLK_IS_CRITICAL),
528
GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", -1,
529
SCU1_CLK_STOP, 5, CLK_IS_CRITICAL),
530
GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", -1,
531
SCU1_CLK_STOP, 6, CLK_IS_CRITICAL),
532
GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", -1,
533
SCU1_CLK_STOP, 7, CLK_IS_CRITICAL),
534
GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", -1,
535
SCU1_CLK_STOP, 8, 0),
536
GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", -1,
537
SCU1_CLK_STOP, 9, 0),
538
GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", -1,
539
SCU1_CLK_STOP, 10, 0),
540
GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", SCU1_CLK_UART0,
541
SCU1_CLK_STOP, 11, CLK_IS_CRITICAL),
542
GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", SCU1_CLK_UART1,
543
SCU1_CLK_STOP, 12, CLK_IS_CRITICAL),
544
GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", SCU1_CLK_UART2,
545
SCU1_CLK_STOP, 13, CLK_IS_CRITICAL),
546
GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", SCU1_CLK_UART3,
547
SCU1_CLK_STOP, 14, CLK_IS_CRITICAL),
548
GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", -1, SCU1_CLK_STOP, 15, 0),
549
GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", SCU1_CLK_I3C,
550
SCU1_CLK_STOP, 16, 0),
551
GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", SCU1_CLK_I3C,
552
SCU1_CLK_STOP, 17, 0),
553
GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", SCU1_CLK_I3C,
554
SCU1_CLK_STOP, 18, 0),
555
GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", SCU1_CLK_I3C,
556
SCU1_CLK_STOP, 19, 0),
557
GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", SCU1_CLK_I3C,
558
SCU1_CLK_STOP, 20, 0),
559
GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", SCU1_CLK_I3C,
560
SCU1_CLK_STOP, 21, 0),
561
GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", SCU1_CLK_I3C,
562
SCU1_CLK_STOP, 22, 0),
563
GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", SCU1_CLK_I3C,
564
SCU1_CLK_STOP, 23, 0),
565
GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", SCU1_CLK_I3C,
566
SCU1_CLK_STOP, 24, 0),
567
GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", SCU1_CLK_I3C,
568
SCU1_CLK_STOP, 25, 0),
569
GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", SCU1_CLK_I3C,
570
SCU1_CLK_STOP, 26, 0),
571
GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", SCU1_CLK_I3C,
572
SCU1_CLK_STOP, 27, 0),
573
GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", SCU1_CLK_I3C,
574
SCU1_CLK_STOP, 28, 0),
575
GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", SCU1_CLK_I3C,
576
SCU1_CLK_STOP, 29, 0),
577
GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", SCU1_CLK_I3C,
578
SCU1_CLK_STOP, 30, 0),
579
GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", SCU1_CLK_I3C,
580
SCU1_CLK_STOP, 31, 0),
581
GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", SCU1_CLK_UART5,
582
SCU1_CLK_STOP2, 0, CLK_IS_CRITICAL),
583
GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", SCU1_CLK_UART6,
584
SCU1_CLK_STOP2, 1, CLK_IS_CRITICAL),
585
GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", SCU1_CLK_UART7,
586
SCU1_CLK_STOP2, 2, CLK_IS_CRITICAL),
587
GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", SCU1_CLK_UART8,
588
SCU1_CLK_STOP2, 3, CLK_IS_CRITICAL),
589
GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", SCU1_CLK_UART9,
590
SCU1_CLK_STOP2, 4, 0),
591
GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", SCU1_CLK_UART10,
592
SCU1_CLK_STOP2, 5, 0),
593
GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", SCU1_CLK_UART11,
594
SCU1_CLK_STOP2, 6, 0),
595
GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", SCU1_CLK_UART12,
596
SCU1_CLK_STOP2, 7, 0),
597
GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", -1, SCU1_CLK_STOP2, 8, 0),
598
GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", -1,
599
SCU1_CLK_STOP2, 9, 0),
600
GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", -1,
601
SCU1_CLK_STOP2, 10, 0),
602
GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", -1,
603
SCU1_CLK_STOP2, 11, CLK_IS_CRITICAL),
604
GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", -1,
605
SCU1_CLK_STOP2, 12, 0),
606
GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", SCU1_CLK_CAN,
607
SCU1_CLK_STOP2, 13, 0),
608
GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", -1,
609
SCU1_CLK_STOP2, 14, 0),
610
GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", -1,
611
SCU1_CLK_STOP2, 15, CLK_IS_CRITICAL),
612
GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", -1,
613
SCU1_CLK_STOP2, 16, CLK_IS_CRITICAL),
614
GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", -1,
615
SCU1_CLK_STOP2, 17, 0),
616
GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", -1,
617
SCU1_CLK_STOP2, 18, 0),
618
GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", -1,
619
SCU1_CLK_STOP2, 19, 0),
620
};
621
622
static struct clk_hw *ast2700_clk_hw_register_fixed_display(void __iomem *reg, const char *name,
623
struct ast2700_clk_ctrl *clk_ctrl)
624
{
625
unsigned int mult, div, r, n;
626
u32 xdclk;
627
u32 val;
628
629
val = readl(clk_ctrl->base + SCU0_CLK_SEL2);
630
if (val & BIT(29))
631
xdclk = 800 * HZ_PER_MHZ;
632
else
633
xdclk = 1000 * HZ_PER_MHZ;
634
635
val = readl(reg);
636
r = val & GENMASK(15, 0);
637
n = (val >> 16) & GENMASK(15, 0);
638
mult = r;
639
div = 2 * n;
640
641
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 0, (xdclk * mult) / div);
642
}
643
644
static struct clk_hw *ast2700_clk_hw_register_hpll(void __iomem *reg,
645
const char *name, const struct clk_hw *parent_hw,
646
struct ast2700_clk_ctrl *clk_ctrl)
647
{
648
unsigned int mult, div;
649
u32 val;
650
651
val = readl(clk_ctrl->base + SCU0_HWSTRAP1);
652
if ((readl(clk_ctrl->base) & REVISION_ID) && (val & BIT(3))) {
653
switch ((val & GENMASK(4, 2)) >> 2) {
654
case 2:
655
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
656
0, 1800 * HZ_PER_MHZ);
657
case 3:
658
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
659
0, 1700 * HZ_PER_MHZ);
660
case 6:
661
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
662
0, 1200 * HZ_PER_MHZ);
663
case 7:
664
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
665
0, 800 * HZ_PER_MHZ);
666
default:
667
return ERR_PTR(-EINVAL);
668
}
669
} else if ((val & GENMASK(3, 2)) != 0) {
670
switch ((val & GENMASK(3, 2)) >> 2) {
671
case 1:
672
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
673
0, 1900 * HZ_PER_MHZ);
674
case 2:
675
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
676
0, 1800 * HZ_PER_MHZ);
677
case 3:
678
return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
679
0, 1700 * HZ_PER_MHZ);
680
default:
681
return ERR_PTR(-EINVAL);
682
}
683
} else {
684
val = readl(reg);
685
686
if (val & BIT(24)) {
687
/* Pass through mode */
688
mult = 1;
689
div = 1;
690
} else {
691
u32 m = val & 0x1fff;
692
u32 n = (val >> 13) & 0x3f;
693
u32 p = (val >> 19) & 0xf;
694
695
mult = (m + 1) / (2 * (n + 1));
696
div = p + 1;
697
}
698
}
699
700
return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
701
parent_hw, 0, mult, div);
702
}
703
704
static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem *reg,
705
const char *name, const struct clk_hw *parent_hw,
706
struct ast2700_clk_ctrl *clk_ctrl)
707
{
708
int scu = clk_ctrl->clk_data->scu;
709
unsigned int mult, div;
710
u32 val = readl(reg);
711
712
if (val & BIT(24)) {
713
/* Pass through mode */
714
mult = 1;
715
div = 1;
716
} else {
717
u32 m = val & 0x1fff;
718
u32 n = (val >> 13) & 0x3f;
719
u32 p = (val >> 19) & 0xf;
720
721
if (scu) {
722
mult = (m + 1) / (n + 1);
723
div = p + 1;
724
} else {
725
if (clk_idx == SCU0_CLK_MPLL) {
726
mult = m / (n + 1);
727
div = p + 1;
728
} else {
729
mult = (m + 1) / (2 * (n + 1));
730
div = p + 1;
731
}
732
}
733
}
734
735
return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
736
parent_hw, 0, mult, div);
737
}
738
739
static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg, const char *name,
740
const struct clk_hw *parent_hw,
741
struct ast2700_clk_ctrl *clk_ctrl)
742
{
743
unsigned int mult, div;
744
u32 val = readl(reg);
745
u32 r = val & 0xff;
746
u32 n = (val >> 8) & 0x3ff;
747
748
mult = r;
749
div = n * 2;
750
751
return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
752
parent_hw, 0, mult, div);
753
}
754
755
static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void __iomem *reg,
756
const char *name, const struct clk_hw *parent_hw,
757
struct ast2700_clk_ctrl *clk_ctrl)
758
{
759
u32 div = 0;
760
761
if (clk_idx == SCU0_CLK_MPHY) {
762
div = readl(reg) + 1;
763
} else if (clk_idx == SCU0_CLK_U2PHY_REFCLK) {
764
if (readl(clk_ctrl->base) & REVISION_ID)
765
div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 4;
766
else
767
div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 1;
768
} else {
769
return ERR_PTR(-EINVAL);
770
}
771
772
return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
773
parent_hw, 0, 1, div);
774
}
775
776
static int ast2700_clk_is_enabled(struct clk_hw *hw)
777
{
778
struct clk_gate *gate = to_clk_gate(hw);
779
u32 clk = BIT(gate->bit_idx);
780
u32 reg;
781
782
reg = readl(gate->reg);
783
784
return !(reg & clk);
785
}
786
787
static int ast2700_clk_enable(struct clk_hw *hw)
788
{
789
struct clk_gate *gate = to_clk_gate(hw);
790
u32 clk = BIT(gate->bit_idx);
791
792
if (readl(gate->reg) & clk)
793
writel(clk, gate->reg + 0x04);
794
795
return 0;
796
}
797
798
static void ast2700_clk_disable(struct clk_hw *hw)
799
{
800
struct clk_gate *gate = to_clk_gate(hw);
801
u32 clk = BIT(gate->bit_idx);
802
803
/* Clock is set to enable, so use write to set register */
804
writel(clk, gate->reg);
805
}
806
807
static const struct clk_ops ast2700_clk_gate_ops = {
808
.enable = ast2700_clk_enable,
809
.disable = ast2700_clk_disable,
810
.is_enabled = ast2700_clk_is_enabled,
811
};
812
813
static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const char *name,
814
const struct clk_hw *parent_hw,
815
void __iomem *reg, u8 clock_idx,
816
unsigned long flags, spinlock_t *lock)
817
{
818
struct clk_init_data init;
819
struct clk_gate *gate;
820
struct clk_hw *hw;
821
int ret = -EINVAL;
822
823
gate = kzalloc_obj(*gate);
824
if (!gate)
825
return ERR_PTR(-ENOMEM);
826
827
init.name = name;
828
init.ops = &ast2700_clk_gate_ops;
829
init.flags = flags;
830
init.parent_names = NULL;
831
init.parent_hws = parent_hw ? &parent_hw : NULL;
832
init.parent_data = NULL;
833
init.num_parents = parent_hw ? 1 : 0;
834
835
gate->reg = reg;
836
gate->bit_idx = clock_idx;
837
gate->flags = 0;
838
gate->lock = lock;
839
gate->hw.init = &init;
840
841
hw = &gate->hw;
842
ret = clk_hw_register(dev, hw);
843
if (ret) {
844
kfree(gate);
845
hw = ERR_PTR(ret);
846
}
847
848
return hw;
849
}
850
851
static void ast2700_soc1_configure_i3c_clk(struct ast2700_clk_ctrl *clk_ctrl)
852
{
853
if (readl(clk_ctrl->base) & REVISION_ID) {
854
u32 val;
855
856
/* I3C 250MHz = HPLL/4 */
857
val = readl(clk_ctrl->base + SCU1_CLK_SEL2) & ~SCU1_CLK_I3C_DIV_MASK;
858
val |= FIELD_PREP(SCU1_CLK_I3C_DIV_MASK, SCU1_CLK_I3C_DIV(4));
859
writel(val, clk_ctrl->base + SCU1_CLK_SEL2);
860
}
861
}
862
863
static inline const struct clk_hw *get_parent_hw_or_null(struct clk_hw **hws, int idx)
864
{
865
if (idx < 0)
866
return NULL;
867
else
868
return hws[idx];
869
}
870
871
static int ast2700_soc_clk_probe(struct platform_device *pdev)
872
{
873
const struct ast2700_clk_data *clk_data;
874
struct clk_hw_onecell_data *clk_hw_data;
875
struct ast2700_clk_ctrl *clk_ctrl;
876
struct device *dev = &pdev->dev;
877
struct auxiliary_device *adev;
878
void __iomem *clk_base;
879
struct clk_hw **hws;
880
char *reset_name;
881
int ret;
882
int i;
883
884
clk_ctrl = devm_kzalloc(dev, sizeof(*clk_ctrl), GFP_KERNEL);
885
if (!clk_ctrl)
886
return -ENOMEM;
887
clk_ctrl->dev = dev;
888
dev_set_drvdata(&pdev->dev, clk_ctrl);
889
890
spin_lock_init(&clk_ctrl->lock);
891
892
clk_base = devm_platform_ioremap_resource(pdev, 0);
893
if (IS_ERR(clk_base))
894
return PTR_ERR(clk_base);
895
896
clk_ctrl->base = clk_base;
897
898
clk_data = device_get_match_data(dev);
899
if (!clk_data)
900
return -ENODEV;
901
902
clk_ctrl->clk_data = clk_data;
903
reset_name = devm_kasprintf(dev, GFP_KERNEL, "reset%d", clk_data->scu);
904
905
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, clk_data->nr_clks),
906
GFP_KERNEL);
907
if (!clk_hw_data)
908
return -ENOMEM;
909
910
clk_hw_data->num = clk_data->nr_clks;
911
hws = clk_hw_data->hws;
912
913
if (clk_data->scu)
914
ast2700_soc1_configure_i3c_clk(clk_ctrl);
915
916
for (i = 0; i < clk_data->nr_clks; i++) {
917
const struct ast2700_clk_info *clk = &clk_data->clk_info[i];
918
const struct clk_hw *phw = NULL;
919
unsigned int id = clk->id;
920
void __iomem *reg = NULL;
921
922
if (id >= clk_hw_data->num || hws[id]) {
923
dev_err(dev, "clk id %u invalid for %s\n", id, clk->name);
924
return -EINVAL;
925
}
926
927
if (clk->type == CLK_FIXED) {
928
const struct ast2700_clk_fixed_rate_data *fixed_rate = &clk->data.rate;
929
930
hws[id] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0,
931
fixed_rate->fixed_rate);
932
} else if (clk->type == CLK_FIXED_FACTOR) {
933
const struct ast2700_clk_fixed_factor_data *factor = &clk->data.factor;
934
935
phw = hws[factor->parent_id];
936
hws[id] = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk->name,
937
phw, 0, factor->mult,
938
factor->div);
939
} else if (clk->type == CLK_FIXED_DISPLAY) {
940
reg = clk_ctrl->base + clk->data.display_rate.reg;
941
942
hws[id] = ast2700_clk_hw_register_fixed_display(reg, clk->name, clk_ctrl);
943
} else if (clk->type == CLK_HPLL) {
944
const struct ast2700_clk_pll_data *pll = &clk->data.pll;
945
946
reg = clk_ctrl->base + pll->reg;
947
phw = hws[pll->parent_id];
948
hws[id] = ast2700_clk_hw_register_hpll(reg, clk->name, phw, clk_ctrl);
949
} else if (clk->type == CLK_PLL) {
950
const struct ast2700_clk_pll_data *pll = &clk->data.pll;
951
952
reg = clk_ctrl->base + pll->reg;
953
phw = hws[pll->parent_id];
954
hws[id] = ast2700_clk_hw_register_pll(id, reg, clk->name, phw, clk_ctrl);
955
} else if (clk->type == CLK_UART_PLL) {
956
const struct ast2700_clk_pll_data *pll = &clk->data.pll;
957
958
reg = clk_ctrl->base + pll->reg;
959
phw = hws[pll->parent_id];
960
hws[id] = ast2700_clk_hw_register_uartpll(reg, clk->name, phw, clk_ctrl);
961
} else if (clk->type == CLK_MUX) {
962
const struct ast2700_clk_mux_data *mux = &clk->data.mux;
963
964
reg = clk_ctrl->base + mux->reg;
965
for (int j = 0; j < mux->num_parents; j++) {
966
unsigned int pid = mux->parent_ids[j];
967
968
mux->parent_hws[j] = hws[pid];
969
}
970
971
hws[id] = devm_clk_hw_register_mux_parent_hws(dev, clk->name,
972
mux->parent_hws,
973
mux->num_parents, 0,
974
reg, mux->bit_shift,
975
mux->bit_width, 0,
976
&clk_ctrl->lock);
977
} else if (clk->type == CLK_MISC) {
978
const struct ast2700_clk_pll_data *pll = &clk->data.pll;
979
980
reg = clk_ctrl->base + pll->reg;
981
phw = hws[pll->parent_id];
982
hws[id] = ast2700_clk_hw_register_misc(id, reg, clk->name, phw, clk_ctrl);
983
} else if (clk->type == CLK_DIVIDER) {
984
const struct ast2700_clk_div_data *divider = &clk->data.div;
985
986
reg = clk_ctrl->base + divider->reg;
987
phw = hws[divider->parent_id];
988
hws[id] = clk_hw_register_divider_table_parent_hw(dev, clk->name,
989
phw,
990
0, reg,
991
divider->bit_shift,
992
divider->bit_width, 0,
993
divider->div_table,
994
&clk_ctrl->lock);
995
} else if (clk->type == CLK_GATE_ASPEED) {
996
const struct ast2700_clk_gate_data *gate = &clk->data.gate;
997
998
phw = get_parent_hw_or_null(hws, gate->parent_id);
999
reg = clk_ctrl->base + gate->reg;
1000
hws[id] = ast2700_clk_hw_register_gate(dev, clk->name, phw, reg, gate->bit,
1001
gate->flags, &clk_ctrl->lock);
1002
} else {
1003
const struct ast2700_clk_gate_data *gate = &clk->data.gate;
1004
1005
phw = get_parent_hw_or_null(hws, gate->parent_id);
1006
reg = clk_ctrl->base + gate->reg;
1007
hws[id] = devm_clk_hw_register_gate_parent_hw(dev, clk->name, phw,
1008
gate->flags, reg, gate->bit,
1009
0, &clk_ctrl->lock);
1010
}
1011
1012
if (IS_ERR(hws[id]))
1013
return PTR_ERR(hws[id]);
1014
}
1015
1016
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
1017
if (ret)
1018
return ret;
1019
1020
adev = devm_auxiliary_device_create(dev, reset_name, (__force void *)clk_base);
1021
if (!adev)
1022
return -ENODEV;
1023
1024
return 0;
1025
}
1026
1027
static const struct ast2700_clk_data ast2700_clk0_data = {
1028
.scu = 0,
1029
.nr_clks = ARRAY_SIZE(ast2700_scu0_clk_info),
1030
.clk_info = ast2700_scu0_clk_info,
1031
};
1032
1033
static const struct ast2700_clk_data ast2700_clk1_data = {
1034
.scu = 1,
1035
.nr_clks = ARRAY_SIZE(ast2700_scu1_clk_info),
1036
.clk_info = ast2700_scu1_clk_info,
1037
};
1038
1039
static const struct of_device_id ast2700_scu_match[] = {
1040
{ .compatible = "aspeed,ast2700-scu0", .data = &ast2700_clk0_data },
1041
{ .compatible = "aspeed,ast2700-scu1", .data = &ast2700_clk1_data },
1042
{ /* sentinel */ }
1043
};
1044
1045
MODULE_DEVICE_TABLE(of, ast2700_scu_match);
1046
1047
static struct platform_driver ast2700_scu_driver = {
1048
.probe = ast2700_soc_clk_probe,
1049
.driver = {
1050
.name = "clk-ast2700",
1051
.of_match_table = ast2700_scu_match,
1052
},
1053
};
1054
1055
module_platform_driver(ast2700_scu_driver);
1056
1057