diff options
Diffstat (limited to 'drivers/clk/rockchip/clk.h')
-rw-r--r-- | drivers/clk/rockchip/clk.h | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h new file mode 100644 index 000000000000..887cbdeca2aa --- /dev/null +++ b/drivers/clk/rockchip/clk.h | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
4 | * | ||
5 | * based on | ||
6 | * | ||
7 | * samsung/clk.h | ||
8 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
9 | * Copyright (c) 2013 Linaro Ltd. | ||
10 | * Author: Thomas Abraham <thomas.ab@samsung.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | */ | ||
22 | |||
23 | #ifndef CLK_ROCKCHIP_CLK_H | ||
24 | #define CLK_ROCKCHIP_CLK_H | ||
25 | |||
26 | #include <linux/io.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/clk-provider.h> | ||
29 | |||
30 | #define HIWORD_UPDATE(val, mask, shift) \ | ||
31 | ((val) << (shift) | (mask) << ((shift) + 16)) | ||
32 | |||
33 | /* register positions shared by RK2928, RK3066 and RK3188 */ | ||
34 | #define RK2928_PLL_CON(x) (x * 0x4) | ||
35 | #define RK2928_MODE_CON 0x40 | ||
36 | #define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44) | ||
37 | #define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0) | ||
38 | #define RK2928_GLB_SRST_FST 0x100 | ||
39 | #define RK2928_GLB_SRST_SND 0x104 | ||
40 | #define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110) | ||
41 | #define RK2928_MISC_CON 0x134 | ||
42 | |||
43 | #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) | ||
44 | #define RK3288_MODE_CON 0x50 | ||
45 | #define RK3288_CLKSEL_CON(x) (x * 0x4 + 0x60) | ||
46 | #define RK3288_CLKGATE_CON(x) (x * 0x4 + 0x160) | ||
47 | #define RK3288_GLB_SRST_FST 0x1b0 | ||
48 | #define RK3288_GLB_SRST_SND 0x1b4 | ||
49 | #define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8) | ||
50 | #define RK3288_MISC_CON 0x1e8 | ||
51 | |||
52 | enum rockchip_pll_type { | ||
53 | pll_rk3066, | ||
54 | }; | ||
55 | |||
56 | #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ | ||
57 | { \ | ||
58 | .rate = _rate##U, \ | ||
59 | .nr = _nr, \ | ||
60 | .nf = _nf, \ | ||
61 | .no = _no, \ | ||
62 | .bwadj = (_nf >> 1), \ | ||
63 | } | ||
64 | |||
65 | struct rockchip_pll_rate_table { | ||
66 | unsigned long rate; | ||
67 | unsigned int nr; | ||
68 | unsigned int nf; | ||
69 | unsigned int no; | ||
70 | unsigned int bwadj; | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * struct rockchip_pll_clock: information about pll clock | ||
75 | * @id: platform specific id of the clock. | ||
76 | * @name: name of this pll clock. | ||
77 | * @parent_name: name of the parent clock. | ||
78 | * @flags: optional flags for basic clock. | ||
79 | * @con_offset: offset of the register for configuring the PLL. | ||
80 | * @mode_offset: offset of the register for configuring the PLL-mode. | ||
81 | * @mode_shift: offset inside the mode-register for the mode of this pll. | ||
82 | * @lock_shift: offset inside the lock register for the lock status. | ||
83 | * @type: Type of PLL to be registered. | ||
84 | * @rate_table: Table of usable pll rates | ||
85 | */ | ||
86 | struct rockchip_pll_clock { | ||
87 | unsigned int id; | ||
88 | const char *name; | ||
89 | const char **parent_names; | ||
90 | u8 num_parents; | ||
91 | unsigned long flags; | ||
92 | int con_offset; | ||
93 | int mode_offset; | ||
94 | int mode_shift; | ||
95 | int lock_shift; | ||
96 | enum rockchip_pll_type type; | ||
97 | struct rockchip_pll_rate_table *rate_table; | ||
98 | }; | ||
99 | |||
100 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ | ||
101 | _lshift, _rtable) \ | ||
102 | { \ | ||
103 | .id = _id, \ | ||
104 | .type = _type, \ | ||
105 | .name = _name, \ | ||
106 | .parent_names = _pnames, \ | ||
107 | .num_parents = ARRAY_SIZE(_pnames), \ | ||
108 | .flags = CLK_GET_RATE_NOCACHE | _flags, \ | ||
109 | .con_offset = _con, \ | ||
110 | .mode_offset = _mode, \ | ||
111 | .mode_shift = _mshift, \ | ||
112 | .lock_shift = _lshift, \ | ||
113 | .rate_table = _rtable, \ | ||
114 | } | ||
115 | |||
116 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | ||
117 | const char *name, const char **parent_names, u8 num_parents, | ||
118 | void __iomem *base, int con_offset, int grf_lock_offset, | ||
119 | int lock_shift, int reg_mode, int mode_shift, | ||
120 | struct rockchip_pll_rate_table *rate_table, | ||
121 | spinlock_t *lock); | ||
122 | |||
123 | #define PNAME(x) static const char *x[] __initconst | ||
124 | |||
125 | enum rockchip_clk_branch_type { | ||
126 | branch_composite, | ||
127 | branch_mux, | ||
128 | branch_divider, | ||
129 | branch_fraction_divider, | ||
130 | branch_gate, | ||
131 | }; | ||
132 | |||
133 | struct rockchip_clk_branch { | ||
134 | unsigned int id; | ||
135 | enum rockchip_clk_branch_type branch_type; | ||
136 | const char *name; | ||
137 | const char **parent_names; | ||
138 | u8 num_parents; | ||
139 | unsigned long flags; | ||
140 | int muxdiv_offset; | ||
141 | u8 mux_shift; | ||
142 | u8 mux_width; | ||
143 | u8 mux_flags; | ||
144 | u8 div_shift; | ||
145 | u8 div_width; | ||
146 | u8 div_flags; | ||
147 | struct clk_div_table *div_table; | ||
148 | int gate_offset; | ||
149 | u8 gate_shift; | ||
150 | u8 gate_flags; | ||
151 | }; | ||
152 | |||
153 | #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ | ||
154 | df, go, gs, gf) \ | ||
155 | { \ | ||
156 | .id = _id, \ | ||
157 | .branch_type = branch_composite, \ | ||
158 | .name = cname, \ | ||
159 | .parent_names = pnames, \ | ||
160 | .num_parents = ARRAY_SIZE(pnames), \ | ||
161 | .flags = f, \ | ||
162 | .muxdiv_offset = mo, \ | ||
163 | .mux_shift = ms, \ | ||
164 | .mux_width = mw, \ | ||
165 | .mux_flags = mf, \ | ||
166 | .div_shift = ds, \ | ||
167 | .div_width = dw, \ | ||
168 | .div_flags = df, \ | ||
169 | .gate_offset = go, \ | ||
170 | .gate_shift = gs, \ | ||
171 | .gate_flags = gf, \ | ||
172 | } | ||
173 | |||
174 | #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ | ||
175 | go, gs, gf) \ | ||
176 | { \ | ||
177 | .id = _id, \ | ||
178 | .branch_type = branch_composite, \ | ||
179 | .name = cname, \ | ||
180 | .parent_names = (const char *[]){ pname }, \ | ||
181 | .num_parents = 1, \ | ||
182 | .flags = f, \ | ||
183 | .muxdiv_offset = mo, \ | ||
184 | .div_shift = ds, \ | ||
185 | .div_width = dw, \ | ||
186 | .div_flags = df, \ | ||
187 | .gate_offset = go, \ | ||
188 | .gate_shift = gs, \ | ||
189 | .gate_flags = gf, \ | ||
190 | } | ||
191 | |||
192 | #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ | ||
193 | df, dt, go, gs, gf) \ | ||
194 | { \ | ||
195 | .id = _id, \ | ||
196 | .branch_type = branch_composite, \ | ||
197 | .name = cname, \ | ||
198 | .parent_names = (const char *[]){ pname }, \ | ||
199 | .num_parents = 1, \ | ||
200 | .flags = f, \ | ||
201 | .muxdiv_offset = mo, \ | ||
202 | .div_shift = ds, \ | ||
203 | .div_width = dw, \ | ||
204 | .div_flags = df, \ | ||
205 | .div_table = dt, \ | ||
206 | .gate_offset = go, \ | ||
207 | .gate_shift = gs, \ | ||
208 | .gate_flags = gf, \ | ||
209 | } | ||
210 | |||
211 | #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ | ||
212 | go, gs, gf) \ | ||
213 | { \ | ||
214 | .id = _id, \ | ||
215 | .branch_type = branch_composite, \ | ||
216 | .name = cname, \ | ||
217 | .parent_names = pnames, \ | ||
218 | .num_parents = ARRAY_SIZE(pnames), \ | ||
219 | .flags = f, \ | ||
220 | .muxdiv_offset = mo, \ | ||
221 | .mux_shift = ms, \ | ||
222 | .mux_width = mw, \ | ||
223 | .mux_flags = mf, \ | ||
224 | .gate_offset = go, \ | ||
225 | .gate_shift = gs, \ | ||
226 | .gate_flags = gf, \ | ||
227 | } | ||
228 | |||
229 | #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ | ||
230 | ds, dw, df) \ | ||
231 | { \ | ||
232 | .id = _id, \ | ||
233 | .branch_type = branch_composite, \ | ||
234 | .name = cname, \ | ||
235 | .parent_names = pnames, \ | ||
236 | .num_parents = ARRAY_SIZE(pnames), \ | ||
237 | .flags = f, \ | ||
238 | .muxdiv_offset = mo, \ | ||
239 | .mux_shift = ms, \ | ||
240 | .mux_width = mw, \ | ||
241 | .mux_flags = mf, \ | ||
242 | .div_shift = ds, \ | ||
243 | .div_width = dw, \ | ||
244 | .div_flags = df, \ | ||
245 | .gate_offset = -1, \ | ||
246 | } | ||
247 | |||
248 | #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ | ||
249 | { \ | ||
250 | .id = _id, \ | ||
251 | .branch_type = branch_fraction_divider, \ | ||
252 | .name = cname, \ | ||
253 | .parent_names = (const char *[]){ pname }, \ | ||
254 | .num_parents = 1, \ | ||
255 | .flags = f, \ | ||
256 | .muxdiv_offset = mo, \ | ||
257 | .div_shift = 16, \ | ||
258 | .div_width = 16, \ | ||
259 | .div_flags = df, \ | ||
260 | .gate_offset = go, \ | ||
261 | .gate_shift = gs, \ | ||
262 | .gate_flags = gf, \ | ||
263 | } | ||
264 | |||
265 | #define MUX(_id, cname, pnames, f, o, s, w, mf) \ | ||
266 | { \ | ||
267 | .id = _id, \ | ||
268 | .branch_type = branch_mux, \ | ||
269 | .name = cname, \ | ||
270 | .parent_names = pnames, \ | ||
271 | .num_parents = ARRAY_SIZE(pnames), \ | ||
272 | .flags = f, \ | ||
273 | .muxdiv_offset = o, \ | ||
274 | .mux_shift = s, \ | ||
275 | .mux_width = w, \ | ||
276 | .mux_flags = mf, \ | ||
277 | .gate_offset = -1, \ | ||
278 | } | ||
279 | |||
280 | #define DIV(_id, cname, pname, f, o, s, w, df) \ | ||
281 | { \ | ||
282 | .id = _id, \ | ||
283 | .branch_type = branch_divider, \ | ||
284 | .name = cname, \ | ||
285 | .parent_names = (const char *[]){ pname }, \ | ||
286 | .num_parents = 1, \ | ||
287 | .flags = f, \ | ||
288 | .muxdiv_offset = o, \ | ||
289 | .div_shift = s, \ | ||
290 | .div_width = w, \ | ||
291 | .div_flags = df, \ | ||
292 | .gate_offset = -1, \ | ||
293 | } | ||
294 | |||
295 | #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ | ||
296 | { \ | ||
297 | .id = _id, \ | ||
298 | .branch_type = branch_divider, \ | ||
299 | .name = cname, \ | ||
300 | .parent_names = (const char *[]){ pname }, \ | ||
301 | .num_parents = 1, \ | ||
302 | .flags = f, \ | ||
303 | .muxdiv_offset = o, \ | ||
304 | .div_shift = s, \ | ||
305 | .div_width = w, \ | ||
306 | .div_flags = df, \ | ||
307 | .div_table = dt, \ | ||
308 | } | ||
309 | |||
310 | #define GATE(_id, cname, pname, f, o, b, gf) \ | ||
311 | { \ | ||
312 | .id = _id, \ | ||
313 | .branch_type = branch_gate, \ | ||
314 | .name = cname, \ | ||
315 | .parent_names = (const char *[]){ pname }, \ | ||
316 | .num_parents = 1, \ | ||
317 | .flags = f, \ | ||
318 | .gate_offset = o, \ | ||
319 | .gate_shift = b, \ | ||
320 | .gate_flags = gf, \ | ||
321 | } | ||
322 | |||
323 | |||
324 | void rockchip_clk_init(struct device_node *np, void __iomem *base, | ||
325 | unsigned long nr_clks); | ||
326 | struct regmap *rockchip_clk_get_grf(void); | ||
327 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); | ||
328 | void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, | ||
329 | unsigned int nr_clk); | ||
330 | void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, | ||
331 | unsigned int nr_pll, int grf_lock_offset); | ||
332 | |||
333 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) | ||
334 | |||
335 | #ifdef CONFIG_RESET_CONTROLLER | ||
336 | void rockchip_register_softrst(struct device_node *np, | ||
337 | unsigned int num_regs, | ||
338 | void __iomem *base, u8 flags); | ||
339 | #else | ||
340 | static inline void rockchip_register_softrst(struct device_node *np, | ||
341 | unsigned int num_regs, | ||
342 | void __iomem *base, u8 flags) | ||
343 | { | ||
344 | } | ||
345 | #endif | ||
346 | |||
347 | #endif | ||