Commit | Line | Data |
---|---|---|
a245fecb HS |
1 | /* |
2 | * Copyright (c) 2014 MundoReader S.L. | |
3 | * Author: Heiko Stuebner <heiko@sntech.de> | |
4 | * | |
9c4d6e55 XZ |
5 | * Copyright (c) 2015 Rockchip Electronics Co. Ltd. |
6 | * Author: Xing Zheng <zhengxing@rock-chips.com> | |
7 | * | |
a245fecb HS |
8 | * based on |
9 | * | |
10 | * samsung/clk.h | |
11 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | |
12 | * Copyright (c) 2013 Linaro Ltd. | |
13 | * Author: Thomas Abraham <thomas.ab@samsung.com> | |
14 | * | |
15 | * This program is free software; you can redistribute it and/or modify | |
16 | * it under the terms of the GNU General Public License as published by | |
17 | * the Free Software Foundation; either version 2 of the License, or | |
18 | * (at your option) any later version. | |
19 | * | |
20 | * This program is distributed in the hope that it will be useful, | |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 | * GNU General Public License for more details. | |
24 | */ | |
25 | ||
26 | #ifndef CLK_ROCKCHIP_CLK_H | |
27 | #define CLK_ROCKCHIP_CLK_H | |
28 | ||
29 | #include <linux/io.h> | |
ef1d9fee | 30 | #include <linux/clk-provider.h> |
f684ff8b SB |
31 | |
32 | struct clk; | |
a245fecb HS |
33 | |
34 | #define HIWORD_UPDATE(val, mask, shift) \ | |
35 | ((val) << (shift) | (mask) << ((shift) + 16)) | |
36 | ||
2d7884a7 | 37 | #define RK2928_PLL_CON(x) ((x) * 0x4) |
a245fecb | 38 | #define RK2928_MODE_CON 0x40 |
2d7884a7 HS |
39 | #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) |
40 | #define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0) | |
a245fecb HS |
41 | #define RK2928_GLB_SRST_FST 0x100 |
42 | #define RK2928_GLB_SRST_SND 0x104 | |
2d7884a7 | 43 | #define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110) |
a245fecb HS |
44 | #define RK2928_MISC_CON 0x134 |
45 | ||
5190c08b XZ |
46 | #define RK3036_SDMMC_CON0 0x144 |
47 | #define RK3036_SDMMC_CON1 0x148 | |
48 | #define RK3036_SDIO_CON0 0x14c | |
49 | #define RK3036_SDIO_CON1 0x150 | |
50 | #define RK3036_EMMC_CON0 0x154 | |
51 | #define RK3036_EMMC_CON1 0x158 | |
52 | ||
307a2e9a JC |
53 | #define RK3228_GLB_SRST_FST 0x1f0 |
54 | #define RK3228_GLB_SRST_SND 0x1f4 | |
55 | #define RK3228_SDMMC_CON0 0x1c0 | |
56 | #define RK3228_SDMMC_CON1 0x1c4 | |
57 | #define RK3228_SDIO_CON0 0x1c8 | |
58 | #define RK3228_SDIO_CON1 0x1cc | |
59 | #define RK3228_EMMC_CON0 0x1d8 | |
60 | #define RK3228_EMMC_CON1 0x1dc | |
61 | ||
b9e4ba54 HS |
62 | #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) |
63 | #define RK3288_MODE_CON 0x50 | |
2d7884a7 HS |
64 | #define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60) |
65 | #define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160) | |
b9e4ba54 HS |
66 | #define RK3288_GLB_SRST_FST 0x1b0 |
67 | #define RK3288_GLB_SRST_SND 0x1b4 | |
2d7884a7 | 68 | #define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8) |
b9e4ba54 | 69 | #define RK3288_MISC_CON 0x1e8 |
89bf26cb AS |
70 | #define RK3288_SDMMC_CON0 0x200 |
71 | #define RK3288_SDMMC_CON1 0x204 | |
72 | #define RK3288_SDIO0_CON0 0x208 | |
73 | #define RK3288_SDIO0_CON1 0x20c | |
74 | #define RK3288_SDIO1_CON0 0x210 | |
75 | #define RK3288_SDIO1_CON1 0x214 | |
76 | #define RK3288_EMMC_CON0 0x218 | |
77 | #define RK3288_EMMC_CON1 0x21c | |
b9e4ba54 | 78 | |
3536c97a HS |
79 | #define RK3368_PLL_CON(x) RK2928_PLL_CON(x) |
80 | #define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100) | |
81 | #define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200) | |
82 | #define RK3368_GLB_SRST_FST 0x280 | |
83 | #define RK3368_GLB_SRST_SND 0x284 | |
84 | #define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300) | |
85 | #define RK3368_MISC_CON 0x380 | |
86 | #define RK3368_SDMMC_CON0 0x400 | |
87 | #define RK3368_SDMMC_CON1 0x404 | |
88 | #define RK3368_SDIO0_CON0 0x408 | |
89 | #define RK3368_SDIO0_CON1 0x40c | |
90 | #define RK3368_SDIO1_CON0 0x410 | |
91 | #define RK3368_SDIO1_CON1 0x414 | |
92 | #define RK3368_EMMC_CON0 0x418 | |
93 | #define RK3368_EMMC_CON1 0x41c | |
94 | ||
11551005 XZ |
95 | #define RK3399_PLL_CON(x) RK2928_PLL_CON(x) |
96 | #define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100) | |
97 | #define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300) | |
98 | #define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400) | |
99 | #define RK3399_GLB_SRST_FST 0x500 | |
100 | #define RK3399_GLB_SRST_SND 0x504 | |
101 | #define RK3399_GLB_CNT_TH 0x508 | |
102 | #define RK3399_MISC_CON 0x50c | |
103 | #define RK3399_RST_CON 0x510 | |
104 | #define RK3399_RST_ST 0x514 | |
105 | #define RK3399_SDMMC_CON0 0x580 | |
106 | #define RK3399_SDMMC_CON1 0x584 | |
107 | #define RK3399_SDIO_CON0 0x588 | |
108 | #define RK3399_SDIO_CON1 0x58c | |
109 | ||
110 | #define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x) | |
111 | #define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80) | |
112 | #define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100) | |
113 | #define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110) | |
114 | ||
90c59025 | 115 | enum rockchip_pll_type { |
9c4d6e55 | 116 | pll_rk3036, |
90c59025 | 117 | pll_rk3066, |
b40baccd | 118 | pll_rk3399, |
90c59025 HS |
119 | }; |
120 | ||
9c4d6e55 XZ |
121 | #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ |
122 | _postdiv2, _dsmpd, _frac) \ | |
123 | { \ | |
124 | .rate = _rate##U, \ | |
125 | .fbdiv = _fbdiv, \ | |
126 | .postdiv1 = _postdiv1, \ | |
127 | .refdiv = _refdiv, \ | |
128 | .postdiv2 = _postdiv2, \ | |
129 | .dsmpd = _dsmpd, \ | |
130 | .frac = _frac, \ | |
131 | } | |
132 | ||
90c59025 HS |
133 | #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ |
134 | { \ | |
135 | .rate = _rate##U, \ | |
136 | .nr = _nr, \ | |
137 | .nf = _nf, \ | |
138 | .no = _no, \ | |
2bbfe001 | 139 | .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ |
90c59025 HS |
140 | } |
141 | ||
2bbfe001 | 142 | #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ |
49ed9ee4 KY |
143 | { \ |
144 | .rate = _rate##U, \ | |
145 | .nr = _nr, \ | |
146 | .nf = _nf, \ | |
147 | .no = _no, \ | |
2bbfe001 | 148 | .nb = _nb, \ |
49ed9ee4 KY |
149 | } |
150 | ||
ef1d9fee | 151 | /** |
2af2544d | 152 | * struct rockchip_clk_provider - information about clock provider |
ef1d9fee XZ |
153 | * @reg_base: virtual address for the register base. |
154 | * @clk_data: holds clock related data like clk* and number of clocks. | |
155 | * @cru_node: device-node of the clock-provider | |
156 | * @grf: regmap of the general-register-files syscon | |
157 | * @lock: maintains exclusion between callbacks for a given clock-provider. | |
158 | */ | |
159 | struct rockchip_clk_provider { | |
160 | void __iomem *reg_base; | |
161 | struct clk_onecell_data clk_data; | |
162 | struct device_node *cru_node; | |
163 | struct regmap *grf; | |
164 | spinlock_t lock; | |
165 | }; | |
166 | ||
90c59025 HS |
167 | struct rockchip_pll_rate_table { |
168 | unsigned long rate; | |
169 | unsigned int nr; | |
170 | unsigned int nf; | |
171 | unsigned int no; | |
2bbfe001 | 172 | unsigned int nb; |
b40baccd | 173 | /* for RK3036/RK3399 */ |
9c4d6e55 XZ |
174 | unsigned int fbdiv; |
175 | unsigned int postdiv1; | |
176 | unsigned int refdiv; | |
177 | unsigned int postdiv2; | |
178 | unsigned int dsmpd; | |
179 | unsigned int frac; | |
90c59025 HS |
180 | }; |
181 | ||
182 | /** | |
2af2544d | 183 | * struct rockchip_pll_clock - information about pll clock |
90c59025 HS |
184 | * @id: platform specific id of the clock. |
185 | * @name: name of this pll clock. | |
2af2544d SL |
186 | * @parent_names: name of the parent clock. |
187 | * @num_parents: number of parents | |
90c59025 HS |
188 | * @flags: optional flags for basic clock. |
189 | * @con_offset: offset of the register for configuring the PLL. | |
190 | * @mode_offset: offset of the register for configuring the PLL-mode. | |
191 | * @mode_shift: offset inside the mode-register for the mode of this pll. | |
192 | * @lock_shift: offset inside the lock register for the lock status. | |
193 | * @type: Type of PLL to be registered. | |
4f8a7c54 | 194 | * @pll_flags: hardware-specific flags |
90c59025 | 195 | * @rate_table: Table of usable pll rates |
0bb66d3b HS |
196 | * |
197 | * Flags: | |
198 | * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the | |
199 | * rate_table parameters and ajust them if necessary. | |
90c59025 HS |
200 | */ |
201 | struct rockchip_pll_clock { | |
202 | unsigned int id; | |
203 | const char *name; | |
4a1caed3 | 204 | const char *const *parent_names; |
90c59025 HS |
205 | u8 num_parents; |
206 | unsigned long flags; | |
207 | int con_offset; | |
208 | int mode_offset; | |
209 | int mode_shift; | |
210 | int lock_shift; | |
211 | enum rockchip_pll_type type; | |
4f8a7c54 | 212 | u8 pll_flags; |
90c59025 HS |
213 | struct rockchip_pll_rate_table *rate_table; |
214 | }; | |
215 | ||
0bb66d3b HS |
216 | #define ROCKCHIP_PLL_SYNC_RATE BIT(0) |
217 | ||
90c59025 | 218 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ |
4f8a7c54 | 219 | _lshift, _pflags, _rtable) \ |
90c59025 HS |
220 | { \ |
221 | .id = _id, \ | |
222 | .type = _type, \ | |
223 | .name = _name, \ | |
224 | .parent_names = _pnames, \ | |
225 | .num_parents = ARRAY_SIZE(_pnames), \ | |
226 | .flags = CLK_GET_RATE_NOCACHE | _flags, \ | |
227 | .con_offset = _con, \ | |
228 | .mode_offset = _mode, \ | |
229 | .mode_shift = _mshift, \ | |
230 | .lock_shift = _lshift, \ | |
4f8a7c54 | 231 | .pll_flags = _pflags, \ |
90c59025 HS |
232 | .rate_table = _rtable, \ |
233 | } | |
234 | ||
ef1d9fee XZ |
235 | struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, |
236 | enum rockchip_pll_type pll_type, | |
4a1caed3 | 237 | const char *name, const char *const *parent_names, |
ef1d9fee XZ |
238 | u8 num_parents, int con_offset, int grf_lock_offset, |
239 | int lock_shift, int mode_offset, int mode_shift, | |
240 | struct rockchip_pll_rate_table *rate_table, | |
e6cebc72 | 241 | unsigned long flags, u8 clk_pll_flags); |
90c59025 | 242 | |
f6fba5f6 HS |
243 | struct rockchip_cpuclk_clksel { |
244 | int reg; | |
245 | u32 val; | |
246 | }; | |
247 | ||
248 | #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 | |
249 | struct rockchip_cpuclk_rate_table { | |
250 | unsigned long prate; | |
251 | struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; | |
252 | }; | |
253 | ||
254 | /** | |
03ae1747 | 255 | * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock |
f6fba5f6 HS |
256 | * @core_reg: register offset of the core settings register |
257 | * @div_core_shift: core divider offset used to divide the pll value | |
258 | * @div_core_mask: core divider mask | |
268aebaa XZ |
259 | * @mux_core_alt: mux value to select alternate parent |
260 | * @mux_core_main: mux value to select main parent of core | |
f6fba5f6 | 261 | * @mux_core_shift: offset of the core multiplexer |
268aebaa | 262 | * @mux_core_mask: core multiplexer mask |
f6fba5f6 HS |
263 | */ |
264 | struct rockchip_cpuclk_reg_data { | |
265 | int core_reg; | |
266 | u8 div_core_shift; | |
267 | u32 div_core_mask; | |
268aebaa XZ |
268 | u8 mux_core_alt; |
269 | u8 mux_core_main; | |
f6fba5f6 | 270 | u8 mux_core_shift; |
268aebaa | 271 | u32 mux_core_mask; |
f6fba5f6 HS |
272 | }; |
273 | ||
274 | struct clk *rockchip_clk_register_cpuclk(const char *name, | |
4a1caed3 | 275 | const char *const *parent_names, u8 num_parents, |
f6fba5f6 HS |
276 | const struct rockchip_cpuclk_reg_data *reg_data, |
277 | const struct rockchip_cpuclk_rate_table *rates, | |
278 | int nrates, void __iomem *reg_base, spinlock_t *lock); | |
279 | ||
89bf26cb | 280 | struct clk *rockchip_clk_register_mmc(const char *name, |
4a1caed3 | 281 | const char *const *parent_names, u8 num_parents, |
89bf26cb AS |
282 | void __iomem *reg, int shift); |
283 | ||
a4f182bf LH |
284 | /* |
285 | * DDRCLK flags, including method of setting the rate | |
286 | * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. | |
287 | */ | |
288 | #define ROCKCHIP_DDRCLK_SIP BIT(0) | |
289 | ||
290 | struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, | |
291 | const char *const *parent_names, | |
292 | u8 num_parents, int mux_offset, | |
293 | int mux_shift, int mux_width, | |
294 | int div_shift, int div_width, | |
295 | int ddr_flags, void __iomem *reg_base, | |
296 | spinlock_t *lock); | |
297 | ||
8a76f443 HS |
298 | #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) |
299 | ||
300 | struct clk *rockchip_clk_register_inverter(const char *name, | |
301 | const char *const *parent_names, u8 num_parents, | |
302 | void __iomem *reg, int shift, int flags, | |
303 | spinlock_t *lock); | |
304 | ||
4a1caed3 | 305 | #define PNAME(x) static const char *const x[] __initconst |
a245fecb HS |
306 | |
307 | enum rockchip_clk_branch_type { | |
308 | branch_composite, | |
309 | branch_mux, | |
310 | branch_divider, | |
311 | branch_fraction_divider, | |
312 | branch_gate, | |
89bf26cb | 313 | branch_mmc, |
8a76f443 | 314 | branch_inverter, |
29a30c26 | 315 | branch_factor, |
a4f182bf | 316 | branch_ddrclk, |
a245fecb HS |
317 | }; |
318 | ||
319 | struct rockchip_clk_branch { | |
320 | unsigned int id; | |
321 | enum rockchip_clk_branch_type branch_type; | |
322 | const char *name; | |
4a1caed3 | 323 | const char *const *parent_names; |
a245fecb HS |
324 | u8 num_parents; |
325 | unsigned long flags; | |
326 | int muxdiv_offset; | |
327 | u8 mux_shift; | |
328 | u8 mux_width; | |
329 | u8 mux_flags; | |
330 | u8 div_shift; | |
331 | u8 div_width; | |
332 | u8 div_flags; | |
333 | struct clk_div_table *div_table; | |
334 | int gate_offset; | |
335 | u8 gate_shift; | |
336 | u8 gate_flags; | |
8ca1ca8f | 337 | struct rockchip_clk_branch *child; |
a245fecb HS |
338 | }; |
339 | ||
340 | #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ | |
341 | df, go, gs, gf) \ | |
342 | { \ | |
343 | .id = _id, \ | |
344 | .branch_type = branch_composite, \ | |
345 | .name = cname, \ | |
346 | .parent_names = pnames, \ | |
347 | .num_parents = ARRAY_SIZE(pnames), \ | |
348 | .flags = f, \ | |
349 | .muxdiv_offset = mo, \ | |
350 | .mux_shift = ms, \ | |
351 | .mux_width = mw, \ | |
352 | .mux_flags = mf, \ | |
353 | .div_shift = ds, \ | |
354 | .div_width = dw, \ | |
355 | .div_flags = df, \ | |
356 | .gate_offset = go, \ | |
357 | .gate_shift = gs, \ | |
358 | .gate_flags = gf, \ | |
359 | } | |
360 | ||
361 | #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ | |
362 | go, gs, gf) \ | |
363 | { \ | |
364 | .id = _id, \ | |
365 | .branch_type = branch_composite, \ | |
366 | .name = cname, \ | |
367 | .parent_names = (const char *[]){ pname }, \ | |
368 | .num_parents = 1, \ | |
369 | .flags = f, \ | |
370 | .muxdiv_offset = mo, \ | |
371 | .div_shift = ds, \ | |
372 | .div_width = dw, \ | |
373 | .div_flags = df, \ | |
374 | .gate_offset = go, \ | |
375 | .gate_shift = gs, \ | |
376 | .gate_flags = gf, \ | |
377 | } | |
378 | ||
379 | #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ | |
380 | df, dt, go, gs, gf) \ | |
381 | { \ | |
382 | .id = _id, \ | |
383 | .branch_type = branch_composite, \ | |
384 | .name = cname, \ | |
385 | .parent_names = (const char *[]){ pname }, \ | |
386 | .num_parents = 1, \ | |
387 | .flags = f, \ | |
388 | .muxdiv_offset = mo, \ | |
389 | .div_shift = ds, \ | |
390 | .div_width = dw, \ | |
391 | .div_flags = df, \ | |
392 | .div_table = dt, \ | |
393 | .gate_offset = go, \ | |
394 | .gate_shift = gs, \ | |
395 | .gate_flags = gf, \ | |
396 | } | |
397 | ||
398 | #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ | |
399 | go, gs, gf) \ | |
400 | { \ | |
401 | .id = _id, \ | |
402 | .branch_type = branch_composite, \ | |
403 | .name = cname, \ | |
404 | .parent_names = pnames, \ | |
405 | .num_parents = ARRAY_SIZE(pnames), \ | |
406 | .flags = f, \ | |
407 | .muxdiv_offset = mo, \ | |
408 | .mux_shift = ms, \ | |
409 | .mux_width = mw, \ | |
410 | .mux_flags = mf, \ | |
411 | .gate_offset = go, \ | |
412 | .gate_shift = gs, \ | |
413 | .gate_flags = gf, \ | |
414 | } | |
415 | ||
416 | #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ | |
417 | ds, dw, df) \ | |
418 | { \ | |
419 | .id = _id, \ | |
420 | .branch_type = branch_composite, \ | |
421 | .name = cname, \ | |
422 | .parent_names = pnames, \ | |
423 | .num_parents = ARRAY_SIZE(pnames), \ | |
424 | .flags = f, \ | |
425 | .muxdiv_offset = mo, \ | |
426 | .mux_shift = ms, \ | |
427 | .mux_width = mw, \ | |
428 | .mux_flags = mf, \ | |
429 | .div_shift = ds, \ | |
430 | .div_width = dw, \ | |
431 | .div_flags = df, \ | |
432 | .gate_offset = -1, \ | |
433 | } | |
434 | ||
6f085072 HS |
435 | #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \ |
436 | mw, mf, ds, dw, df, dt) \ | |
437 | { \ | |
438 | .id = _id, \ | |
439 | .branch_type = branch_composite, \ | |
440 | .name = cname, \ | |
441 | .parent_names = pnames, \ | |
442 | .num_parents = ARRAY_SIZE(pnames), \ | |
443 | .flags = f, \ | |
444 | .muxdiv_offset = mo, \ | |
445 | .mux_shift = ms, \ | |
446 | .mux_width = mw, \ | |
447 | .mux_flags = mf, \ | |
448 | .div_shift = ds, \ | |
449 | .div_width = dw, \ | |
450 | .div_flags = df, \ | |
451 | .div_table = dt, \ | |
452 | .gate_offset = -1, \ | |
453 | } | |
454 | ||
a245fecb HS |
455 | #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ |
456 | { \ | |
457 | .id = _id, \ | |
458 | .branch_type = branch_fraction_divider, \ | |
459 | .name = cname, \ | |
460 | .parent_names = (const char *[]){ pname }, \ | |
461 | .num_parents = 1, \ | |
462 | .flags = f, \ | |
463 | .muxdiv_offset = mo, \ | |
464 | .div_shift = 16, \ | |
465 | .div_width = 16, \ | |
466 | .div_flags = df, \ | |
467 | .gate_offset = go, \ | |
468 | .gate_shift = gs, \ | |
469 | .gate_flags = gf, \ | |
470 | } | |
471 | ||
8ca1ca8f HS |
472 | #define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \ |
473 | { \ | |
474 | .id = _id, \ | |
475 | .branch_type = branch_fraction_divider, \ | |
476 | .name = cname, \ | |
477 | .parent_names = (const char *[]){ pname }, \ | |
478 | .num_parents = 1, \ | |
479 | .flags = f, \ | |
480 | .muxdiv_offset = mo, \ | |
481 | .div_shift = 16, \ | |
482 | .div_width = 16, \ | |
483 | .div_flags = df, \ | |
484 | .gate_offset = go, \ | |
485 | .gate_shift = gs, \ | |
486 | .gate_flags = gf, \ | |
5b738403 | 487 | .child = ch, \ |
8ca1ca8f HS |
488 | } |
489 | ||
9387bfd1 XZ |
490 | #define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \ |
491 | { \ | |
492 | .id = _id, \ | |
493 | .branch_type = branch_fraction_divider, \ | |
494 | .name = cname, \ | |
495 | .parent_names = (const char *[]){ pname }, \ | |
496 | .num_parents = 1, \ | |
497 | .flags = f, \ | |
498 | .muxdiv_offset = mo, \ | |
499 | .div_shift = 16, \ | |
500 | .div_width = 16, \ | |
501 | .div_flags = df, \ | |
502 | .gate_offset = -1, \ | |
503 | .child = ch, \ | |
504 | } | |
505 | ||
a4f182bf LH |
506 | #define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, \ |
507 | ds, dw, df) \ | |
508 | { \ | |
509 | .id = _id, \ | |
510 | .branch_type = branch_ddrclk, \ | |
511 | .name = cname, \ | |
512 | .parent_names = pnames, \ | |
513 | .num_parents = ARRAY_SIZE(pnames), \ | |
514 | .flags = f, \ | |
515 | .muxdiv_offset = mo, \ | |
516 | .mux_shift = ms, \ | |
517 | .mux_width = mw, \ | |
518 | .div_shift = ds, \ | |
519 | .div_width = dw, \ | |
520 | .div_flags = df, \ | |
521 | .gate_offset = -1, \ | |
522 | } | |
523 | ||
a245fecb HS |
524 | #define MUX(_id, cname, pnames, f, o, s, w, mf) \ |
525 | { \ | |
526 | .id = _id, \ | |
527 | .branch_type = branch_mux, \ | |
528 | .name = cname, \ | |
529 | .parent_names = pnames, \ | |
530 | .num_parents = ARRAY_SIZE(pnames), \ | |
531 | .flags = f, \ | |
532 | .muxdiv_offset = o, \ | |
533 | .mux_shift = s, \ | |
534 | .mux_width = w, \ | |
535 | .mux_flags = mf, \ | |
536 | .gate_offset = -1, \ | |
537 | } | |
538 | ||
539 | #define DIV(_id, cname, pname, f, o, s, w, df) \ | |
540 | { \ | |
541 | .id = _id, \ | |
542 | .branch_type = branch_divider, \ | |
543 | .name = cname, \ | |
544 | .parent_names = (const char *[]){ pname }, \ | |
545 | .num_parents = 1, \ | |
546 | .flags = f, \ | |
547 | .muxdiv_offset = o, \ | |
548 | .div_shift = s, \ | |
549 | .div_width = w, \ | |
550 | .div_flags = df, \ | |
551 | .gate_offset = -1, \ | |
552 | } | |
553 | ||
554 | #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ | |
555 | { \ | |
556 | .id = _id, \ | |
557 | .branch_type = branch_divider, \ | |
558 | .name = cname, \ | |
559 | .parent_names = (const char *[]){ pname }, \ | |
560 | .num_parents = 1, \ | |
561 | .flags = f, \ | |
562 | .muxdiv_offset = o, \ | |
563 | .div_shift = s, \ | |
564 | .div_width = w, \ | |
565 | .div_flags = df, \ | |
566 | .div_table = dt, \ | |
567 | } | |
568 | ||
569 | #define GATE(_id, cname, pname, f, o, b, gf) \ | |
570 | { \ | |
571 | .id = _id, \ | |
572 | .branch_type = branch_gate, \ | |
573 | .name = cname, \ | |
574 | .parent_names = (const char *[]){ pname }, \ | |
575 | .num_parents = 1, \ | |
576 | .flags = f, \ | |
577 | .gate_offset = o, \ | |
578 | .gate_shift = b, \ | |
579 | .gate_flags = gf, \ | |
580 | } | |
581 | ||
89bf26cb AS |
582 | #define MMC(_id, cname, pname, offset, shift) \ |
583 | { \ | |
584 | .id = _id, \ | |
585 | .branch_type = branch_mmc, \ | |
586 | .name = cname, \ | |
587 | .parent_names = (const char *[]){ pname }, \ | |
588 | .num_parents = 1, \ | |
589 | .muxdiv_offset = offset, \ | |
590 | .div_shift = shift, \ | |
591 | } | |
a245fecb | 592 | |
8a76f443 HS |
593 | #define INVERTER(_id, cname, pname, io, is, if) \ |
594 | { \ | |
595 | .id = _id, \ | |
596 | .branch_type = branch_inverter, \ | |
597 | .name = cname, \ | |
598 | .parent_names = (const char *[]){ pname }, \ | |
599 | .num_parents = 1, \ | |
600 | .muxdiv_offset = io, \ | |
601 | .div_shift = is, \ | |
602 | .div_flags = if, \ | |
603 | } | |
604 | ||
29a30c26 HS |
605 | #define FACTOR(_id, cname, pname, f, fm, fd) \ |
606 | { \ | |
607 | .id = _id, \ | |
608 | .branch_type = branch_factor, \ | |
609 | .name = cname, \ | |
610 | .parent_names = (const char *[]){ pname }, \ | |
611 | .num_parents = 1, \ | |
612 | .flags = f, \ | |
613 | .div_shift = fm, \ | |
614 | .div_width = fd, \ | |
615 | } | |
616 | ||
617 | #define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ | |
618 | { \ | |
619 | .id = _id, \ | |
620 | .branch_type = branch_factor, \ | |
621 | .name = cname, \ | |
622 | .parent_names = (const char *[]){ pname }, \ | |
623 | .num_parents = 1, \ | |
624 | .flags = f, \ | |
625 | .div_shift = fm, \ | |
626 | .div_width = fd, \ | |
627 | .gate_offset = go, \ | |
628 | .gate_shift = gb, \ | |
629 | .gate_flags = gf, \ | |
630 | } | |
631 | ||
ef1d9fee XZ |
632 | struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, |
633 | void __iomem *base, unsigned long nr_clks); | |
634 | void rockchip_clk_of_add_provider(struct device_node *np, | |
635 | struct rockchip_clk_provider *ctx); | |
ef1d9fee XZ |
636 | void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, |
637 | struct clk *clk, unsigned int id); | |
638 | void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, | |
639 | struct rockchip_clk_branch *list, | |
a245fecb | 640 | unsigned int nr_clk); |
ef1d9fee XZ |
641 | void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, |
642 | struct rockchip_pll_clock *pll_list, | |
90c59025 | 643 | unsigned int nr_pll, int grf_lock_offset); |
ef1d9fee XZ |
644 | void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, |
645 | unsigned int lookup_id, const char *name, | |
4a1caed3 | 646 | const char *const *parent_names, u8 num_parents, |
f6fba5f6 HS |
647 | const struct rockchip_cpuclk_reg_data *reg_data, |
648 | const struct rockchip_cpuclk_rate_table *rates, | |
649 | int nrates); | |
692d8328 | 650 | void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); |
ef1d9fee XZ |
651 | void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, |
652 | unsigned int reg, void (*cb)(void)); | |
a245fecb | 653 | |
85fa0c7f HS |
654 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) |
655 | ||
656 | #ifdef CONFIG_RESET_CONTROLLER | |
657 | void rockchip_register_softrst(struct device_node *np, | |
658 | unsigned int num_regs, | |
659 | void __iomem *base, u8 flags); | |
660 | #else | |
661 | static inline void rockchip_register_softrst(struct device_node *np, | |
662 | unsigned int num_regs, | |
663 | void __iomem *base, u8 flags) | |
664 | { | |
665 | } | |
666 | #endif | |
667 | ||
a245fecb | 668 | #endif |