blob: 32c334d7fc87435fc295b63bffb0d19babee87a9 [file] [log] [blame]
Heiko Stübnera245fec2014-07-03 01:58:39 +02001/*
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
Heiko Stübner90c59022014-07-03 01:59:10 +020043enum rockchip_pll_type {
44 pll_rk3066,
45};
46
47#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
48{ \
49 .rate = _rate##U, \
50 .nr = _nr, \
51 .nf = _nf, \
52 .no = _no, \
53 .bwadj = (_nf >> 1), \
54}
55
56struct rockchip_pll_rate_table {
57 unsigned long rate;
58 unsigned int nr;
59 unsigned int nf;
60 unsigned int no;
61 unsigned int bwadj;
62};
63
64/**
65 * struct rockchip_pll_clock: information about pll clock
66 * @id: platform specific id of the clock.
67 * @name: name of this pll clock.
68 * @parent_name: name of the parent clock.
69 * @flags: optional flags for basic clock.
70 * @con_offset: offset of the register for configuring the PLL.
71 * @mode_offset: offset of the register for configuring the PLL-mode.
72 * @mode_shift: offset inside the mode-register for the mode of this pll.
73 * @lock_shift: offset inside the lock register for the lock status.
74 * @type: Type of PLL to be registered.
75 * @rate_table: Table of usable pll rates
76 */
77struct rockchip_pll_clock {
78 unsigned int id;
79 const char *name;
80 const char **parent_names;
81 u8 num_parents;
82 unsigned long flags;
83 int con_offset;
84 int mode_offset;
85 int mode_shift;
86 int lock_shift;
87 enum rockchip_pll_type type;
88 struct rockchip_pll_rate_table *rate_table;
89};
90
91#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \
92 _lshift, _rtable) \
93 { \
94 .id = _id, \
95 .type = _type, \
96 .name = _name, \
97 .parent_names = _pnames, \
98 .num_parents = ARRAY_SIZE(_pnames), \
99 .flags = CLK_GET_RATE_NOCACHE | _flags, \
100 .con_offset = _con, \
101 .mode_offset = _mode, \
102 .mode_shift = _mshift, \
103 .lock_shift = _lshift, \
104 .rate_table = _rtable, \
105 }
106
107struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
108 const char *name, const char **parent_names, u8 num_parents,
109 void __iomem *base, int con_offset, int grf_lock_offset,
110 int lock_shift, int reg_mode, int mode_shift,
111 struct rockchip_pll_rate_table *rate_table,
112 spinlock_t *lock);
113
Heiko Stübnera245fec2014-07-03 01:58:39 +0200114#define PNAME(x) static const char *x[] __initconst
115
116enum rockchip_clk_branch_type {
117 branch_composite,
118 branch_mux,
119 branch_divider,
120 branch_fraction_divider,
121 branch_gate,
122};
123
124struct rockchip_clk_branch {
125 unsigned int id;
126 enum rockchip_clk_branch_type branch_type;
127 const char *name;
128 const char **parent_names;
129 u8 num_parents;
130 unsigned long flags;
131 int muxdiv_offset;
132 u8 mux_shift;
133 u8 mux_width;
134 u8 mux_flags;
135 u8 div_shift;
136 u8 div_width;
137 u8 div_flags;
138 struct clk_div_table *div_table;
139 int gate_offset;
140 u8 gate_shift;
141 u8 gate_flags;
142};
143
144#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
145 df, go, gs, gf) \
146 { \
147 .id = _id, \
148 .branch_type = branch_composite, \
149 .name = cname, \
150 .parent_names = pnames, \
151 .num_parents = ARRAY_SIZE(pnames), \
152 .flags = f, \
153 .muxdiv_offset = mo, \
154 .mux_shift = ms, \
155 .mux_width = mw, \
156 .mux_flags = mf, \
157 .div_shift = ds, \
158 .div_width = dw, \
159 .div_flags = df, \
160 .gate_offset = go, \
161 .gate_shift = gs, \
162 .gate_flags = gf, \
163 }
164
165#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
166 go, gs, gf) \
167 { \
168 .id = _id, \
169 .branch_type = branch_composite, \
170 .name = cname, \
171 .parent_names = (const char *[]){ pname }, \
172 .num_parents = 1, \
173 .flags = f, \
174 .muxdiv_offset = mo, \
175 .div_shift = ds, \
176 .div_width = dw, \
177 .div_flags = df, \
178 .gate_offset = go, \
179 .gate_shift = gs, \
180 .gate_flags = gf, \
181 }
182
183#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
184 df, dt, go, gs, gf) \
185 { \
186 .id = _id, \
187 .branch_type = branch_composite, \
188 .name = cname, \
189 .parent_names = (const char *[]){ pname }, \
190 .num_parents = 1, \
191 .flags = f, \
192 .muxdiv_offset = mo, \
193 .div_shift = ds, \
194 .div_width = dw, \
195 .div_flags = df, \
196 .div_table = dt, \
197 .gate_offset = go, \
198 .gate_shift = gs, \
199 .gate_flags = gf, \
200 }
201
202#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \
203 go, gs, gf) \
204 { \
205 .id = _id, \
206 .branch_type = branch_composite, \
207 .name = cname, \
208 .parent_names = pnames, \
209 .num_parents = ARRAY_SIZE(pnames), \
210 .flags = f, \
211 .muxdiv_offset = mo, \
212 .mux_shift = ms, \
213 .mux_width = mw, \
214 .mux_flags = mf, \
215 .gate_offset = go, \
216 .gate_shift = gs, \
217 .gate_flags = gf, \
218 }
219
220#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
221 ds, dw, df) \
222 { \
223 .id = _id, \
224 .branch_type = branch_composite, \
225 .name = cname, \
226 .parent_names = pnames, \
227 .num_parents = ARRAY_SIZE(pnames), \
228 .flags = f, \
229 .muxdiv_offset = mo, \
230 .mux_shift = ms, \
231 .mux_width = mw, \
232 .mux_flags = mf, \
233 .div_shift = ds, \
234 .div_width = dw, \
235 .div_flags = df, \
236 .gate_offset = -1, \
237 }
238
239#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
240 { \
241 .id = _id, \
242 .branch_type = branch_fraction_divider, \
243 .name = cname, \
244 .parent_names = (const char *[]){ pname }, \
245 .num_parents = 1, \
246 .flags = f, \
247 .muxdiv_offset = mo, \
248 .div_shift = 16, \
249 .div_width = 16, \
250 .div_flags = df, \
251 .gate_offset = go, \
252 .gate_shift = gs, \
253 .gate_flags = gf, \
254 }
255
256#define MUX(_id, cname, pnames, f, o, s, w, mf) \
257 { \
258 .id = _id, \
259 .branch_type = branch_mux, \
260 .name = cname, \
261 .parent_names = pnames, \
262 .num_parents = ARRAY_SIZE(pnames), \
263 .flags = f, \
264 .muxdiv_offset = o, \
265 .mux_shift = s, \
266 .mux_width = w, \
267 .mux_flags = mf, \
268 .gate_offset = -1, \
269 }
270
271#define DIV(_id, cname, pname, f, o, s, w, df) \
272 { \
273 .id = _id, \
274 .branch_type = branch_divider, \
275 .name = cname, \
276 .parent_names = (const char *[]){ pname }, \
277 .num_parents = 1, \
278 .flags = f, \
279 .muxdiv_offset = o, \
280 .div_shift = s, \
281 .div_width = w, \
282 .div_flags = df, \
283 .gate_offset = -1, \
284 }
285
286#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
287 { \
288 .id = _id, \
289 .branch_type = branch_divider, \
290 .name = cname, \
291 .parent_names = (const char *[]){ pname }, \
292 .num_parents = 1, \
293 .flags = f, \
294 .muxdiv_offset = o, \
295 .div_shift = s, \
296 .div_width = w, \
297 .div_flags = df, \
298 .div_table = dt, \
299 }
300
301#define GATE(_id, cname, pname, f, o, b, gf) \
302 { \
303 .id = _id, \
304 .branch_type = branch_gate, \
305 .name = cname, \
306 .parent_names = (const char *[]){ pname }, \
307 .num_parents = 1, \
308 .flags = f, \
309 .gate_offset = o, \
310 .gate_shift = b, \
311 .gate_flags = gf, \
312 }
313
314
315void rockchip_clk_init(struct device_node *np, void __iomem *base,
316 unsigned long nr_clks);
Heiko Stübner90c59022014-07-03 01:59:10 +0200317struct regmap *rockchip_clk_get_grf(void);
Heiko Stübnera245fec2014-07-03 01:58:39 +0200318void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
319void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
320 unsigned int nr_clk);
Heiko Stübner90c59022014-07-03 01:59:10 +0200321void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
322 unsigned int nr_pll, int grf_lock_offset);
Heiko Stübnera245fec2014-07-03 01:58:39 +0200323
Heiko Stübner85fa0c72014-07-03 01:59:39 +0200324#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
325
326#ifdef CONFIG_RESET_CONTROLLER
327void rockchip_register_softrst(struct device_node *np,
328 unsigned int num_regs,
329 void __iomem *base, u8 flags);
330#else
331static inline void rockchip_register_softrst(struct device_node *np,
332 unsigned int num_regs,
333 void __iomem *base, u8 flags)
334{
335}
336#endif
337
Heiko Stübnera245fec2014-07-03 01:58:39 +0200338#endif