1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Copyright (c) 2014 MundoReader S.L.
4 * Author: Heiko Stuebner <heiko@sntech.de>
5 *
6 * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
7 * Author: Xing Zheng <zhengxing@rock-chips.com>
8 *
9 * based on
10 *
11 * samsung/clk.h
12 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
13 * Copyright (c) 2013 Linaro Ltd.
14 * Author: Thomas Abraham <thomas.ab@samsung.com>
15 */
16
17 #ifndef CLK_ROCKCHIP_CLK_H
18 #define CLK_ROCKCHIP_CLK_H
19
20 #include <linux/io.h>
21 #include <linux/clk-provider.h>
22
23 struct clk;
24
25 #define HIWORD_UPDATE(val, mask, shift) ((val) << (shift) | (mask) << ((shift) + 16))
26
27 /* register positions shared by PX30, RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
28 #define BOOST_PLL_H_CON(x) ((x)*0x4)
29 #define BOOST_CLK_CON 0x0008
30 #define BOOST_BOOST_CON 0x000c
31 #define BOOST_SWITCH_CNT 0x0010
32 #define BOOST_HIGH_PERF_CNT0 0x0014
33 #define BOOST_HIGH_PERF_CNT1 0x0018
34 #define BOOST_STATIS_THRESHOLD 0x001c
35 #define BOOST_SHORT_SWITCH_CNT 0x0020
36 #define BOOST_SWITCH_THRESHOLD 0x0024
37 #define BOOST_FSM_STATUS 0x0028
38 #define BOOST_PLL_L_CON(x) ((x)*0x4 + 0x2c)
39 #define BOOST_PLL_CON_MASK 0xffff
40 #define BOOST_CORE_DIV_MASK 0x1f
41 #define BOOST_CORE_DIV_SHIFT 0
42 #define BOOST_BACKUP_PLL_MASK 0x3
43 #define BOOST_BACKUP_PLL_SHIFT 8
44 #define BOOST_BACKUP_PLL_USAGE_MASK 0x1
45 #define BOOST_BACKUP_PLL_USAGE_SHIFT 12
46 #define BOOST_BACKUP_PLL_USAGE_BORROW 0
47 #define BOOST_BACKUP_PLL_USAGE_TARGET 1
48 #define BOOST_ENABLE_MASK 0x1
49 #define BOOST_ENABLE_SHIFT 0
50 #define BOOST_RECOVERY_MASK 0x1
51 #define BOOST_RECOVERY_SHIFT 1
52 #define BOOST_SW_CTRL_MASK 0x1
53 #define BOOST_SW_CTRL_SHIFT 2
54 #define BOOST_LOW_FREQ_EN_MASK 0x1
55 #define BOOST_LOW_FREQ_EN_SHIFT 3
56 #define BOOST_STATIS_ENABLE_MASK 0x1
57 #define BOOST_STATIS_ENABLE_SHIFT 4
58 #define BOOST_BUSY_STATE BIT(8)
59
60 #define PX30_PLL_CON(x) ((x)*0x4)
61 #define PX30_CLKSEL_CON(x) ((x)*0x4 + 0x100)
62 #define PX30_CLKGATE_CON(x) ((x)*0x4 + 0x200)
63 #define PX30_GLB_SRST_FST 0xb8
64 #define PX30_GLB_SRST_SND 0xbc
65 #define PX30_SOFTRST_CON(x) ((x)*0x4 + 0x300)
66 #define PX30_MODE_CON 0xa0
67 #define PX30_MISC_CON 0xa4
68 #define PX30_SDMMC_CON0 0x380
69 #define PX30_SDMMC_CON1 0x384
70 #define PX30_SDIO_CON0 0x388
71 #define PX30_SDIO_CON1 0x38c
72 #define PX30_EMMC_CON0 0x390
73 #define PX30_EMMC_CON1 0x394
74
75 #define PX30_PMU_PLL_CON(x) ((x)*0x4)
76 #define PX30_PMU_CLKSEL_CON(x) ((x)*0x4 + 0x40)
77 #define PX30_PMU_CLKGATE_CON(x) ((x)*0x4 + 0x80)
78 #define PX30_PMU_MODE 0x0020
79
80 #define RV1108_PLL_CON(x) ((x)*0x4)
81 #define RV1108_CLKSEL_CON(x) ((x)*0x4 + 0x60)
82 #define RV1108_CLKGATE_CON(x) ((x)*0x4 + 0x120)
83 #define RV1108_SOFTRST_CON(x) ((x)*0x4 + 0x180)
84 #define RV1108_GLB_SRST_FST 0x1c0
85 #define RV1108_GLB_SRST_SND 0x1c4
86 #define RV1108_MISC_CON 0x1cc
87 #define RV1108_SDMMC_CON0 0x1d8
88 #define RV1108_SDMMC_CON1 0x1dc
89 #define RV1108_SDIO_CON0 0x1e0
90 #define RV1108_SDIO_CON1 0x1e4
91 #define RV1108_EMMC_CON0 0x1e8
92 #define RV1108_EMMC_CON1 0x1ec
93
94 #define RV1126_PMU_MODE 0x0
95 #define RV1126_PMU_PLL_CON(x) ((x)*0x4 + 0x10)
96 #define RV1126_PMU_CLKSEL_CON(x) ((x)*0x4 + 0x100)
97 #define RV1126_PMU_CLKGATE_CON(x) ((x)*0x4 + 0x180)
98 #define RV1126_PMU_SOFTRST_CON(x) ((x)*0x4 + 0x200)
99 #define RV1126_PLL_CON(x) ((x)*0x4)
100 #define RV1126_MODE_CON 0x90
101 #define RV1126_CLKSEL_CON(x) ((x)*0x4 + 0x100)
102 #define RV1126_CLKGATE_CON(x) ((x)*0x4 + 0x280)
103 #define RV1126_SOFTRST_CON(x) ((x)*0x4 + 0x300)
104 #define RV1126_GLB_SRST_FST 0x408
105 #define RV1126_GLB_SRST_SND 0x40c
106 #define RV1126_SDMMC_CON0 0x440
107 #define RV1126_SDMMC_CON1 0x444
108 #define RV1126_SDIO_CON0 0x448
109 #define RV1126_SDIO_CON1 0x44c
110 #define RV1126_EMMC_CON0 0x450
111 #define RV1126_EMMC_CON1 0x454
112
113 /*
114 * register positions shared by RK1808 RK2928, RK3036,
115 * RK3066, RK3188 and RK3228
116 */
117
118 #define RK1808_PLL_CON(x) ((x)*0x4)
119 #define RK1808_MODE_CON 0xa0
120 #define RK1808_MISC_CON 0xa4
121 #define RK1808_MISC1_CON 0xa8
122 #define RK1808_GLB_SRST_FST 0xb8
123 #define RK1808_GLB_SRST_SND 0xbc
124 #define RK1808_CLKSEL_CON(x) ((x)*0x4 + 0x100)
125 #define RK1808_CLKGATE_CON(x) ((x)*0x4 + 0x230)
126 #define RK1808_SOFTRST_CON(x) ((x)*0x4 + 0x300)
127 #define RK1808_SDMMC_CON0 0x380
128 #define RK1808_SDMMC_CON1 0x384
129 #define RK1808_SDIO_CON0 0x388
130 #define RK1808_SDIO_CON1 0x38c
131 #define RK1808_EMMC_CON0 0x390
132 #define RK1808_EMMC_CON1 0x394
133
134 #define RK1808_PMU_PLL_CON(x) ((x)*0x4 + 0x4000)
135 #define RK1808_PMU_MODE_CON 0x4020
136 #define RK1808_PMU_CLKSEL_CON(x) ((x)*0x4 + 0x4040)
137 #define RK1808_PMU_CLKGATE_CON(x) ((x)*0x4 + 0x4080)
138
139 #define RK2928_PLL_CON(x) ((x)*0x4)
140 #define RK2928_MODE_CON 0x40
141 #define RK2928_CLKSEL_CON(x) ((x)*0x4 + 0x44)
142 #define RK2928_CLKGATE_CON(x) ((x)*0x4 + 0xd0)
143 #define RK2928_GLB_SRST_FST 0x100
144 #define RK2928_GLB_SRST_SND 0x104
145 #define RK2928_SOFTRST_CON(x) ((x)*0x4 + 0x110)
146 #define RK2928_MISC_CON 0x134
147
148 #define RK3036_SDMMC_CON0 0x144
149 #define RK3036_SDMMC_CON1 0x148
150 #define RK3036_SDIO_CON0 0x14c
151 #define RK3036_SDIO_CON1 0x150
152 #define RK3036_EMMC_CON0 0x154
153 #define RK3036_EMMC_CON1 0x158
154
155 #define RK3228_GLB_SRST_FST 0x1f0
156 #define RK3228_GLB_SRST_SND 0x1f4
157 #define RK3228_SDMMC_CON0 0x1c0
158 #define RK3228_SDMMC_CON1 0x1c4
159 #define RK3228_SDIO_CON0 0x1c8
160 #define RK3228_SDIO_CON1 0x1cc
161 #define RK3228_EMMC_CON0 0x1d8
162 #define RK3228_EMMC_CON1 0x1dc
163
164 #define RK3288_PLL_CON(x) RK2928_PLL_CON(x)
165 #define RK3288_MODE_CON 0x50
166 #define RK3288_CLKSEL_CON(x) ((x)*0x4 + 0x60)
167 #define RK3288_CLKGATE_CON(x) ((x)*0x4 + 0x160)
168 #define RK3288_GLB_SRST_FST 0x1b0
169 #define RK3288_GLB_SRST_SND 0x1b4
170 #define RK3288_SOFTRST_CON(x) ((x)*0x4 + 0x1b8)
171 #define RK3288_MISC_CON 0x1e8
172 #define RK3288_SDMMC_CON0 0x200
173 #define RK3288_SDMMC_CON1 0x204
174 #define RK3288_SDIO0_CON0 0x208
175 #define RK3288_SDIO0_CON1 0x20c
176 #define RK3288_SDIO1_CON0 0x210
177 #define RK3288_SDIO1_CON1 0x214
178 #define RK3288_EMMC_CON0 0x218
179 #define RK3288_EMMC_CON1 0x21c
180
181 #define RK3308_PLL_CON(x) RK2928_PLL_CON(x)
182 #define RK3308_CLKSEL_CON(x) ((x)*0x4 + 0x100)
183 #define RK3308_CLKGATE_CON(x) ((x)*0x4 + 0x300)
184 #define RK3308_GLB_SRST_FST 0xb8
185 #define RK3308_SOFTRST_CON(x) ((x)*0x4 + 0x400)
186 #define RK3308_MODE_CON 0xa0
187 #define RK3308_SDMMC_CON0 0x480
188 #define RK3308_SDMMC_CON1 0x484
189 #define RK3308_SDIO_CON0 0x488
190 #define RK3308_SDIO_CON1 0x48c
191 #define RK3308_EMMC_CON0 0x490
192 #define RK3308_EMMC_CON1 0x494
193
194 #define RK3328_PLL_CON(x) RK2928_PLL_CON(x)
195 #define RK3328_CLKSEL_CON(x) ((x)*0x4 + 0x100)
196 #define RK3328_CLKGATE_CON(x) ((x)*0x4 + 0x200)
197 #define RK3328_GRFCLKSEL_CON(x) ((x)*0x4 + 0x100)
198 #define RK3328_GLB_SRST_FST 0x9c
199 #define RK3328_GLB_SRST_SND 0x98
200 #define RK3328_SOFTRST_CON(x) ((x)*0x4 + 0x300)
201 #define RK3328_MODE_CON 0x80
202 #define RK3328_MISC_CON 0x84
203 #define RK3328_SDMMC_CON0 0x380
204 #define RK3328_SDMMC_CON1 0x384
205 #define RK3328_SDIO_CON0 0x388
206 #define RK3328_SDIO_CON1 0x38c
207 #define RK3328_EMMC_CON0 0x390
208 #define RK3328_EMMC_CON1 0x394
209 #define RK3328_SDMMC_EXT_CON0 0x398
210 #define RK3328_SDMMC_EXT_CON1 0x39C
211
212 #define RK3368_PLL_CON(x) RK2928_PLL_CON(x)
213 #define RK3368_CLKSEL_CON(x) ((x)*0x4 + 0x100)
214 #define RK3368_CLKGATE_CON(x) ((x)*0x4 + 0x200)
215 #define RK3368_GLB_SRST_FST 0x280
216 #define RK3368_GLB_SRST_SND 0x284
217 #define RK3368_SOFTRST_CON(x) ((x)*0x4 + 0x300)
218 #define RK3368_MISC_CON 0x380
219 #define RK3368_SDMMC_CON0 0x400
220 #define RK3368_SDMMC_CON1 0x404
221 #define RK3368_SDIO0_CON0 0x408
222 #define RK3368_SDIO0_CON1 0x40c
223 #define RK3368_SDIO1_CON0 0x410
224 #define RK3368_SDIO1_CON1 0x414
225 #define RK3368_EMMC_CON0 0x418
226 #define RK3368_EMMC_CON1 0x41c
227
228 #define RK3399_PLL_CON(x) RK2928_PLL_CON(x)
229 #define RK3399_CLKSEL_CON(x) ((x)*0x4 + 0x100)
230 #define RK3399_CLKGATE_CON(x) ((x)*0x4 + 0x300)
231 #define RK3399_SOFTRST_CON(x) ((x)*0x4 + 0x400)
232 #define RK3399_GLB_SRST_FST 0x500
233 #define RK3399_GLB_SRST_SND 0x504
234 #define RK3399_GLB_CNT_TH 0x508
235 #define RK3399_MISC_CON 0x50c
236 #define RK3399_RST_CON 0x510
237 #define RK3399_RST_ST 0x514
238 #define RK3399_SDMMC_CON0 0x580
239 #define RK3399_SDMMC_CON1 0x584
240 #define RK3399_SDIO_CON0 0x588
241 #define RK3399_SDIO_CON1 0x58c
242
243 #define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x)
244 #define RK3399_PMU_CLKSEL_CON(x) ((x)*0x4 + 0x80)
245 #define RK3399_PMU_CLKGATE_CON(x) ((x)*0x4 + 0x100)
246 #define RK3399_PMU_SOFTRST_CON(x) ((x)*0x4 + 0x110)
247
248 #define RK3568_PLL_CON(x) RK2928_PLL_CON(x)
249 #define RK3568_MODE_CON0 0xc0
250 #define RK3568_MISC_CON0 0xc4
251 #define RK3568_MISC_CON1 0xc8
252 #define RK3568_MISC_CON2 0xcc
253 #define RK3568_GLB_CNT_TH 0xd0
254 #define RK3568_GLB_SRST_FST 0xd4
255 #define RK3568_GLB_SRST_SND 0xd8
256 #define RK3568_GLB_RST_CON 0xdc
257 #define RK3568_GLB_RST_ST 0xe0
258 #define RK3568_CLKSEL_CON(x) ((x)*0x4 + 0x100)
259 #define RK3568_CLKGATE_CON(x) ((x)*0x4 + 0x300)
260 #define RK3568_SOFTRST_CON(x) ((x)*0x4 + 0x400)
261 #define RK3568_SDMMC0_CON0 0x580
262 #define RK3568_SDMMC0_CON1 0x584
263 #define RK3568_SDMMC1_CON0 0x588
264 #define RK3568_SDMMC1_CON1 0x58c
265 #define RK3568_SDMMC2_CON0 0x590
266 #define RK3568_SDMMC2_CON1 0x594
267 #define RK3568_EMMC_CON0 0x598
268 #define RK3568_EMMC_CON1 0x59c
269
270 #define RK3568_PMU_PLL_CON(x) RK2928_PLL_CON(x)
271 #define RK3568_PMU_MODE_CON0 0x80
272 #define RK3568_PMU_CLKSEL_CON(x) ((x)*0x4 + 0x100)
273 #define RK3568_PMU_CLKGATE_CON(x) ((x)*0x4 + 0x180)
274 #define RK3568_PMU_SOFTRST_CON(x) ((x)*0x4 + 0x200)
275
276 enum rockchip_pll_type {
277 pll_rk3036,
278 pll_rk3066,
279 pll_rk3328,
280 pll_rk3399,
281 };
282
283 #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac) \
284 { \
285 .rate = _rate##U, .fbdiv = (_fbdiv), \
286 .postdiv1 = (_postdiv1), .refdiv = (_refdiv), \
287 .postdiv2 = (_postdiv2), \
288 .dsmpd = (_dsmpd), .frac = (_frac), \
289 }
290
291 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
292 { \
293 .rate = _rate##U, \
294 .nr = (_nr), \
295 .nf = (_nf), \
296 .no = (_no), \
297 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \
298 }
299
300 #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \
301 { \
302 .rate = _rate##U, .nr = (_nr), .nf = (_nf), .no = (_no), .nb = (_nb), \
303 }
304
305 /**
306 * struct rockchip_clk_provider - information about clock provider
307 * @reg_base: virtual address for the register base.
308 * @clk_data: holds clock related data like clk* and number of clocks.
309 * @cru_node: device-node of the clock-provider
310 * @grf: regmap of the general-register-files syscon
311 * @lock: maintains exclusion between callbacks for a given clock-provider.
312 */
313 struct rockchip_clk_provider {
314 void __iomem *reg_base;
315 struct clk_onecell_data clk_data;
316 struct device_node *cru_node;
317 struct regmap *grf;
318 struct regmap *pmugrf;
319 spinlock_t lock;
320 };
321
322 struct rockchip_pll_rate_table {
323 unsigned long rate;
324 union {
325 struct {
326 /* for RK3066 */
327 unsigned int nr;
328 unsigned int nf;
329 unsigned int no;
330 unsigned int nb;
331 };
332 struct {
333 /* for RK3036/RK3399 */
334 unsigned int fbdiv;
335 unsigned int postdiv1;
336 unsigned int refdiv;
337 unsigned int postdiv2;
338 unsigned int dsmpd;
339 unsigned int frac;
340 };
341 };
342 };
343
344 /**
345 * struct rockchip_pll_clock - information about pll clock
346 * @id: platform specific id of the clock.
347 * @name: name of this pll clock.
348 * @parent_names: name of the parent clock.
349 * @num_parents: number of parents
350 * @flags: optional flags for basic clock.
351 * @con_offset: offset of the register for configuring the PLL.
352 * @mode_offset: offset of the register for configuring the PLL-mode.
353 * @mode_shift: offset inside the mode-register for the mode of this pll.
354 * @lock_shift: offset inside the lock register for the lock status.
355 * @type: Type of PLL to be registered.
356 * @pll_flags: hardware-specific flags
357 * @rate_table: Table of usable pll rates
358 *
359 * Flags:
360 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
361 * rate_table parameters and ajust them if necessary.
362 */
363 struct rockchip_pll_clock {
364 unsigned int id;
365 const char *name;
366 const char *const *parent_names;
367 u8 num_parents;
368 unsigned long flags;
369 int con_offset;
370 int mode_offset;
371 int mode_shift;
372 int lock_shift;
373 enum rockchip_pll_type type;
374 u8 pll_flags;
375 struct rockchip_pll_rate_table *rate_table;
376 };
377
378 #define ROCKCHIP_PLL_SYNC_RATE BIT(0)
379
380 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, _lshift, _pflags, _rtable) \
381 { \
382 .id = (_id), .type = (_type), .name = (_name), .parent_names = (_pnames), .num_parents = ARRAY_SIZE(_pnames), \
383 .flags = CLK_GET_RATE_NOCACHE | (_flags), .con_offset = (_con), .mode_offset = (_mode), \
384 .mode_shift = (_mshift), .lock_shift = (_lshift), .pll_flags = (_pflags), .rate_table = (_rtable), \
385 }
386
387 struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, enum rockchip_pll_type pll_type,
388 const char *name, const char *const *parent_names, u8 num_parents, int con_offset,
389 int grf_lock_offset, int lock_shift, int mode_offset, int mode_shift,
390 struct rockchip_pll_rate_table *rate_table, unsigned long flags,
391 u8 clk_pll_flags);
392
393 void rockchip_boost_init(struct clk_hw *hw);
394
395 void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw);
396
397 void rockchip_boost_disable_recovery_sw(struct clk_hw *hw);
398
399 void rockchip_boost_add_core_div(struct clk_hw *hw, unsigned long prate);
400
401 struct rockchip_cpuclk_clksel {
402 int reg;
403 u32 val;
404 };
405
406 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 5
407 #define ROCKCHIP_CPUCLK_MAX_CORES 4
408 struct rockchip_cpuclk_rate_table {
409 unsigned long prate;
410 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
411 };
412
413 /**
414 * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock
415 * @core_reg[]: register offset of the cores setting register
416 * @div_core_shift[]: cores divider offset used to divide the pll value
417 * @div_core_mask[]: cores divider mask
418 * @num_cores: number of cpu cores
419 * @mux_core_main: mux value to select main parent of core
420 * @mux_core_shift: offset of the core multiplexer
421 * @mux_core_mask: core multiplexer mask
422 */
423 struct rockchip_cpuclk_reg_data {
424 int core_reg[ROCKCHIP_CPUCLK_MAX_CORES];
425 u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];
426 u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];
427 int num_cores;
428 u8 mux_core_alt;
429 u8 mux_core_main;
430 u8 mux_core_shift;
431 u32 mux_core_mask;
432 const char *pll_name;
433 };
434
435 struct clk *rockchip_clk_register_cpuclk(const char *name, u8 num_parents, struct clk *parent, struct clk *alt_parent,
436 const struct rockchip_cpuclk_reg_data *reg_data,
437 const struct rockchip_cpuclk_rate_table *rates, int nrates,
438 void __iomem *reg_base, spinlock_t *lock);
439
440 struct clk *rockchip_clk_register_mmc(const char *name, const char *const *parent_names, u8 num_parents,
441 void __iomem *reg, int shift);
442
443 /*
444 * DDRCLK flags, including method of setting the rate
445 * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate.
446 * ROCKCHIP_DDRCLK_SCPI: use SCPI APIs to let mcu change ddrclk rate.
447 */
448 #define ROCKCHIP_DDRCLK_SIP BIT(0)
449 #define ROCKCHIP_DDRCLK_SCPI 0x02
450 #define ROCKCHIP_DDRCLK_SIP_V2 0x03
451
452 void rockchip_set_ddrclk_params(void __iomem *params);
453 void rockchip_set_ddrclk_dmcfreq_wait_complete(int (*func)(void));
454
455 struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, const char *const *parent_names, u8 num_parents,
456 int mux_offset, int mux_shift, int mux_width, int div_shift, int div_width,
457 int ddr_flags, void __iomem *reg_base);
458
459 #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0)
460
461 struct clk *rockchip_clk_register_inverter(const char *name, const char *const *parent_names, u8 num_parents,
462 void __iomem *reg, int shift, int flags, spinlock_t *lock);
463
464 struct clk *rockchip_clk_register_muxgrf(const char *name, const char *const *parent_names, u8 num_parents, int flags,
465 struct regmap *grf, int reg, int shift, int width, int mux_flags);
466
467 #define PNAME(x) static const char *const x[] __initconst
468
469 enum rockchip_clk_branch_type {
470 branch_composite,
471 branch_composite_brother,
472 branch_mux,
473 branch_muxgrf,
474 branch_muxpmugrf,
475 branch_divider,
476 branch_fraction_divider,
477 branch_gate,
478 branch_mmc,
479 branch_inverter,
480 branch_factor,
481 branch_ddrclk,
482 branch_half_divider,
483 branch_dclk_divider,
484 };
485
486 struct rockchip_clk_branch {
487 unsigned int id;
488 enum rockchip_clk_branch_type branch_type;
489 const char *name;
490 const char *const *parent_names;
491 u8 num_parents;
492 unsigned long flags;
493 int muxdiv_offset;
494 u8 mux_shift;
495 u8 mux_width;
496 u8 mux_flags;
497 u32 *mux_table;
498 int div_offset;
499 u8 div_shift;
500 u8 div_width;
501 u8 div_flags;
502 struct clk_div_table *div_table;
503 int gate_offset;
504 u8 gate_shift;
505 u8 gate_flags;
506 struct rockchip_clk_branch *child;
507 unsigned long max_prate;
508 };
509
510 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df, go, gs, gf) \
511 { \
512 .id = (_id), .branch_type = branch_composite, .name = (cname), .parent_names = (pnames), \
513 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
514 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = (go), \
515 .gate_shift = (gs), .gate_flags = (gf), \
516 }
517
518 #define COMPOSITE_BROTHER(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df, go, gs, gf, bro) \
519 { \
520 .id = (_id), .branch_type = branch_composite_brother, .name = (cname), .parent_names = (pnames), \
521 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
522 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = (go), \
523 .gate_shift = (gs), .gate_flags = (gf), .child = (bro), \
524 }
525
526 #define COMPOSITE_MUXTBL(_id, cname, pnames, f, mo, ms, mw, mf, mt, ds, dw, df, go, gs, gf) \
527 { \
528 .id = (_id), .branch_type = branch_composite, .name = (cname), .parent_names = (pnames), \
529 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
530 .mux_flags = (mf), .mux_table = (mt), .div_shift = (ds), .div_width = (dw), .div_flags = (df), \
531 .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), \
532 }
533
534 #define COMPOSITE_DIV_OFFSET(_id, _cname, _pnames, _f, _mo, _ms, _mw, _mf, _do, _ds, _dw, _df, _go, _gs, _gf) \
535 { \
536 .id = (_id), .branch_type = branch_composite, .name = (_cname), .parent_names = (_pnames), \
537 .num_parents = ARRAY_SIZE(_pnames), .flags = (_f), \
538 .muxdiv_offset = (_mo), .mux_shift = (_ms), .mux_width = (_mw), \
539 .mux_flags = (_mf), .div_offset = _do, .div_shift = (_ds), .div_width = (_dw), .div_flags = (_df), \
540 .gate_offset = (_go), .gate_shift = (_gs), .gate_flags = (_gf), \
541 }
542
543 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, go, gs, gf) \
544 { \
545 .id = (_id), .branch_type = branch_composite, .name = (cname), \
546 .parent_names = (const char *[]) {pname}, \
547 .num_parents = 1, .flags = (f), .muxdiv_offset = (mo), .div_shift = (ds), .div_width = (dw), \
548 .div_flags = (df), .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), \
549 }
550
551 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw, df, dt, go, gs, gf) \
552 { \
553 .id = (_id), .branch_type = branch_composite, .name = (cname), .parent_names = (const char *[]) {pname}, \
554 .num_parents = 1, .flags = (f), .muxdiv_offset = (mo), .div_shift = (ds), .div_width = (dw), \
555 .div_flags = (df), .div_table = (dt), .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), \
556 }
557
558 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, go, gs, gf) \
559 { \
560 .id = (_id), .branch_type = branch_composite, .name = (cname), .parent_names = (pnames), \
561 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
562 .mux_flags = (mf), .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), \
563 }
564
565 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df) \
566 { \
567 .id = (_id), .branch_type = branch_composite, .name = (cname), .parent_names = (pnames), \
568 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
569 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = -1, \
570 }
571
572 #define COMPOSITE_BROTHER_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df, bro) \
573 { \
574 .id = (_id), .branch_type = branch_composite_brother, .name = (cname), .parent_names = (pnames), \
575 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
576 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = -1, .child = (bro), \
577 }
578
579 #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df, dt) \
580 { \
581 .id = (_id), .branch_type = branch_composite, .name = (cname), .parent_names = (pnames), \
582 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
583 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .div_table = (dt), \
584 .gate_offset = -1, \
585 }
586
587 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf, prate) \
588 { \
589 .id = (_id), .branch_type = branch_fraction_divider, .name = (cname), \
590 .parent_names = (const char *[]) {pname}, \
591 .num_parents = 1, .flags = (f), .muxdiv_offset = (mo), .div_shift = 16, .div_width = 16, .div_flags = (df), \
592 .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), .max_prate = (prate), \
593 }
594
595 #define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch, prate) \
596 { \
597 .id = (_id), .branch_type = branch_fraction_divider, .name = (cname), \
598 .parent_names = (const char *[]) {pname}, \
599 .num_parents = 1, .flags = (f), .muxdiv_offset = (mo), .div_shift = 16, .div_width = 16, .div_flags = (df), \
600 .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), .child = (ch), .max_prate = (prate), \
601 }
602
603 #define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch, prate) \
604 { \
605 .id = (_id), .branch_type = branch_fraction_divider, .name = (cname), \
606 .parent_names = (const char *[]) {pname}, \
607 .num_parents = 1, .flags = (f), .muxdiv_offset = (mo), .div_shift = 16, .div_width = 16, .div_flags = (df), \
608 .gate_offset = -1, .child = (ch), .max_prate = (prate), \
609 }
610
611 #define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, ds, dw, df) \
612 { \
613 .id = (_id), .branch_type = branch_ddrclk, .name = (cname), .parent_names = (pnames), \
614 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
615 .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = -1, \
616 }
617
618 #define MUX(_id, cname, pnames, f, o, s, w, mf) \
619 { \
620 .id = (_id), .branch_type = branch_mux, .name = (cname), .parent_names = (pnames), \
621 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (o), .mux_shift = (s), .mux_width = (w), \
622 .mux_flags = (mf), .gate_offset = -1, \
623 }
624
625 #define MUXTBL(_id, cname, pnames, f, o, s, w, mf, mt) \
626 { \
627 .id = (_id), .branch_type = branch_mux, .name = (cname), .parent_names = (pnames), \
628 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (o), .mux_shift = (s), .mux_width = (w), \
629 .mux_flags = (mf), .gate_offset = -1, .mux_table = (mt), \
630 }
631
632 #define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \
633 { \
634 .id = (_id), .branch_type = branch_muxgrf, .name = (cname), .parent_names = (pnames), \
635 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (o), .mux_shift = (s), .mux_width = (w), \
636 .mux_flags = (mf), .gate_offset = -1, \
637 }
638
639 #define MUXPMUGRF(_id, cname, pnames, f, o, s, w, mf) \
640 { \
641 .id = (_id), .branch_type = branch_muxpmugrf, .name = (cname), .parent_names = (pnames), \
642 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (o), .mux_shift = (s), .mux_width = (w), \
643 .mux_flags = (mf), .gate_offset = -1, \
644 }
645
646 #define DIV(_id, cname, pname, f, o, s, w, df) \
647 { \
648 .id = (_id), .branch_type = branch_divider, .name = (cname), .parent_names = (const char *[]) {pname}, \
649 .num_parents = 1, .flags = (f), .muxdiv_offset = (o), .div_shift = (s), .div_width = (w), .div_flags = (df), \
650 .gate_offset = -1, \
651 }
652
653 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
654 { \
655 .id = (_id), .branch_type = branch_divider, .name = (cname), .parent_names = (const char *[]) {pname}, \
656 .num_parents = 1, .flags = (f), .muxdiv_offset = (o), .div_shift = (s), .div_width = (w), .div_flags = (df), \
657 .div_table = (dt), \
658 }
659
660 #define GATE(_id, cname, pname, f, o, b, gf) \
661 { \
662 .id = (_id), .branch_type = branch_gate, .name = (cname), .parent_names = (const char *[]) {pname}, \
663 .num_parents = 1, .flags = (f), .gate_offset = (o), .gate_shift = (b), .gate_flags = (gf), \
664 }
665
666 #define MMC(_id, cname, pname, offset, shift) \
667 { \
668 .id = (_id), .branch_type = branch_mmc, .name = (cname), .parent_names = (const char *[]) {pname}, \
669 .num_parents = 1, .muxdiv_offset = (offset), .div_shift = (shift), \
670 }
671
672 #define INVERTER(_id, cname, pname, io, _is, _if) \
673 { \
674 .id = (_id), .branch_type = branch_inverter, .name = (cname), .parent_names = (const char *[]) {pname}, \
675 .num_parents = 1, .muxdiv_offset = (io), .div_shift = (_is), .div_flags = (_if), \
676 }
677
678 #define FACTOR(_id, cname, pname, f, fm, fd) \
679 { \
680 .id = (_id), .branch_type = branch_factor, .name = (cname), .parent_names = (const char *[]) {pname}, \
681 .num_parents = 1, .flags = (f), .div_shift = (fm), .div_width = (fd), \
682 }
683
684 #define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \
685 { \
686 .id = (_id), .branch_type = branch_factor, .name = (cname), .parent_names = (const char *[]) {pname}, \
687 .num_parents = 1, .flags = (f), .div_shift = (fm), .div_width = (fd), .gate_offset = (go), .gate_shift = (gb), \
688 .gate_flags = (gf), \
689 }
690
691 #define COMPOSITE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df, go, gs, gf) \
692 { \
693 .id = (_id), .branch_type = branch_half_divider, .name = (cname), .parent_names = (pnames), \
694 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
695 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = (go), \
696 .gate_shift = (gs), .gate_flags = (gf), \
697 }
698
699 #define COMPOSITE_HALFDIV_OFFSET(_id, cname, pnames, f, mo, ms, mw, mf, _do, ds, dw, df, go, gs, gf) \
700 { \
701 .id = (_id), .branch_type = branch_half_divider, .name = (cname), .parent_names = (pnames), \
702 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
703 .mux_flags = (mf), .div_offset = _do, .div_shift = (ds), .div_width = (dw), .div_flags = (df), \
704 .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), \
705 }
706
707 #define COMPOSITE_NOGATE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df) \
708 { \
709 .id = (_id), .branch_type = branch_half_divider, .name = (cname), .parent_names = (pnames), \
710 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
711 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = -1, \
712 }
713
714 #define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, go, gs, gf) \
715 { \
716 .id = (_id), .branch_type = branch_half_divider, .name = (cname), .parent_names = (const char *[]) {pname}, \
717 .num_parents = 1, .flags = (f), .muxdiv_offset = (mo), .div_shift = (ds), .div_width = (dw), \
718 .div_flags = (df), .gate_offset = (go), .gate_shift = (gs), .gate_flags = (gf), \
719 }
720
721 #define DIV_HALF(_id, cname, pname, f, o, s, w, df) \
722 { \
723 .id = (_id), .branch_type = branch_half_divider, .name = (cname), .parent_names = (const char *[]) {pname}, \
724 .num_parents = 1, .flags = (f), .muxdiv_offset = (o), .div_shift = (s), .div_width = (w), .div_flags = (df), \
725 .gate_offset = -1, \
726 }
727
728 #define COMPOSITE_DCLK(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df, go, gs, gf, prate) \
729 { \
730 .id = (_id), .branch_type = branch_dclk_divider, .name = (cname), .parent_names = (pnames), \
731 .num_parents = ARRAY_SIZE(pnames), .flags = (f), .muxdiv_offset = (mo), .mux_shift = (ms), .mux_width = (mw), \
732 .mux_flags = (mf), .div_shift = (ds), .div_width = (dw), .div_flags = (df), .gate_offset = (go), \
733 .gate_shift = (gs), .gate_flags = (gf), .max_prate = (prate), \
734 }
735
736 /* SGRF clocks are only accessible from secure mode, so not controllable */
737 #define SGRF_GATE(_id, cname, pname) FACTOR((_id), cname, pname, 0, 1, 1)
738
739 struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks);
740 void rockchip_clk_of_add_provider(struct device_node *np, struct rockchip_clk_provider *ctx);
741 void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, struct clk *clk, unsigned int id);
742 void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, struct rockchip_clk_branch *list,
743 unsigned int nr_clk);
744 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, struct rockchip_pll_clock *list,
745 unsigned int nr_pll, int grf_lock_offset);
746 void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, unsigned int lookup_id, const char *name,
747 u8 num_parents, struct clk *parent, struct clk *alt_parent,
748 const struct rockchip_cpuclk_reg_data *reg_data,
749 const struct rockchip_cpuclk_rate_table *rates, int nrates);
750 int rockchip_pll_clk_rate_to_scale(struct clk *clk, unsigned long rate);
751 int rockchip_pll_clk_scale_to_rate(struct clk *clk, unsigned int scale);
752 int rockchip_pll_clk_adaptive_scaling(struct clk *clk, int sel);
753 void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, unsigned int reg, void (*cb)(void));
754
755 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
756
757 struct clk *rockchip_clk_register_halfdiv(const char *name, const char *const *parent_names, u8 num_parents,
758 void __iomem *base, int muxdiv_offset, u8 mux_shift, u8 mux_width,
759 u8 mux_flags, int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
760 int gate_offset, u8 gate_shift, u8 gate_flags, unsigned long flags,
761 spinlock_t *lock);
762
763 struct clk *rockchip_clk_register_dclk_branch(const char *name, const char *const *parent_names, u8 num_parents,
764 void __iomem *base, int muxdiv_offset, u8 mux_shift, u8 mux_width,
765 u8 mux_flags, int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
766 struct clk_div_table *div_table, int gate_offset, u8 gate_shift,
767 u8 gate_flags, unsigned long flags, unsigned long max_prate,
768 spinlock_t *lock);
769
770 #ifdef CONFIG_RESET_CONTROLLER
771 void rockchip_register_softrst(struct device_node *np, unsigned int num_regs, void __iomem *base, u8 flags);
772 #else
rockchip_register_softrst(struct device_node * np,unsigned int num_regs,void __iomem * base,u8 flags)773 static inline void rockchip_register_softrst(struct device_node *np, unsigned int num_regs, void __iomem *base,
774 u8 flags)
775 {
776 }
777 #endif
778 extern void (*rk_dump_cru)(void);
779
780 #endif
781