aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/rockchip/clk.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/rockchip/clk.h')
-rw-r--r--drivers/clk/rockchip/clk.h347
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
52enum 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
65struct 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 */
86struct 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
116struct 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
125enum rockchip_clk_branch_type {
126 branch_composite,
127 branch_mux,
128 branch_divider,
129 branch_fraction_divider,
130 branch_gate,
131};
132
133struct 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
324void rockchip_clk_init(struct device_node *np, void __iomem *base,
325 unsigned long nr_clks);
326struct regmap *rockchip_clk_get_grf(void);
327void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
328void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
329 unsigned int nr_clk);
330void 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
336void rockchip_register_softrst(struct device_node *np,
337 unsigned int num_regs,
338 void __iomem *base, u8 flags);
339#else
340static 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