xref: /openbmc/linux/drivers/clk/rockchip/clk.h (revision 3821a065)
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 
28 struct clk;
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 #define RK3288_SDMMC_CON0		0x200
52 #define RK3288_SDMMC_CON1		0x204
53 #define RK3288_SDIO0_CON0		0x208
54 #define RK3288_SDIO0_CON1		0x20c
55 #define RK3288_SDIO1_CON0		0x210
56 #define RK3288_SDIO1_CON1		0x214
57 #define RK3288_EMMC_CON0		0x218
58 #define RK3288_EMMC_CON1		0x21c
59 
60 #define RK3368_PLL_CON(x)		RK2928_PLL_CON(x)
61 #define RK3368_CLKSEL_CON(x)		((x) * 0x4 + 0x100)
62 #define RK3368_CLKGATE_CON(x)		((x) * 0x4 + 0x200)
63 #define RK3368_GLB_SRST_FST		0x280
64 #define RK3368_GLB_SRST_SND		0x284
65 #define RK3368_SOFTRST_CON(x)		((x) * 0x4 + 0x300)
66 #define RK3368_MISC_CON			0x380
67 #define RK3368_SDMMC_CON0		0x400
68 #define RK3368_SDMMC_CON1		0x404
69 #define RK3368_SDIO0_CON0		0x408
70 #define RK3368_SDIO0_CON1		0x40c
71 #define RK3368_SDIO1_CON0		0x410
72 #define RK3368_SDIO1_CON1		0x414
73 #define RK3368_EMMC_CON0		0x418
74 #define RK3368_EMMC_CON1		0x41c
75 
76 enum rockchip_pll_type {
77 	pll_rk3066,
78 };
79 
80 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
81 {						\
82 	.rate	= _rate##U,			\
83 	.nr = _nr,				\
84 	.nf = _nf,				\
85 	.no = _no,				\
86 	.nb = ((_nf) < 2) ? 1 : (_nf) >> 1,	\
87 }
88 
89 #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb)		\
90 {								\
91 	.rate	= _rate##U,					\
92 	.nr = _nr,						\
93 	.nf = _nf,						\
94 	.no = _no,						\
95 	.nb = _nb,						\
96 }
97 
98 struct rockchip_pll_rate_table {
99 	unsigned long rate;
100 	unsigned int nr;
101 	unsigned int nf;
102 	unsigned int no;
103 	unsigned int nb;
104 };
105 
106 /**
107  * struct rockchip_pll_clock: information about pll clock
108  * @id: platform specific id of the clock.
109  * @name: name of this pll clock.
110  * @parent_name: name of the parent clock.
111  * @flags: optional flags for basic clock.
112  * @con_offset: offset of the register for configuring the PLL.
113  * @mode_offset: offset of the register for configuring the PLL-mode.
114  * @mode_shift: offset inside the mode-register for the mode of this pll.
115  * @lock_shift: offset inside the lock register for the lock status.
116  * @type: Type of PLL to be registered.
117  * @pll_flags: hardware-specific flags
118  * @rate_table: Table of usable pll rates
119  *
120  * Flags:
121  * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
122  *	rate_table parameters and ajust them if necessary.
123  */
124 struct rockchip_pll_clock {
125 	unsigned int		id;
126 	const char		*name;
127 	const char		*const *parent_names;
128 	u8			num_parents;
129 	unsigned long		flags;
130 	int			con_offset;
131 	int			mode_offset;
132 	int			mode_shift;
133 	int			lock_shift;
134 	enum rockchip_pll_type	type;
135 	u8			pll_flags;
136 	struct rockchip_pll_rate_table *rate_table;
137 };
138 
139 #define ROCKCHIP_PLL_SYNC_RATE		BIT(0)
140 
141 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift,	\
142 		_lshift, _pflags, _rtable)				\
143 	{								\
144 		.id		= _id,					\
145 		.type		= _type,				\
146 		.name		= _name,				\
147 		.parent_names	= _pnames,				\
148 		.num_parents	= ARRAY_SIZE(_pnames),			\
149 		.flags		= CLK_GET_RATE_NOCACHE | _flags,	\
150 		.con_offset	= _con,					\
151 		.mode_offset	= _mode,				\
152 		.mode_shift	= _mshift,				\
153 		.lock_shift	= _lshift,				\
154 		.pll_flags	= _pflags,				\
155 		.rate_table	= _rtable,				\
156 	}
157 
158 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
159 		const char *name, const char *const *parent_names,
160 		u8 num_parents, void __iomem *base, int con_offset,
161 		int grf_lock_offset, int lock_shift, int reg_mode,
162 		int mode_shift, struct rockchip_pll_rate_table *rate_table,
163 		u8 clk_pll_flags, spinlock_t *lock);
164 
165 struct rockchip_cpuclk_clksel {
166 	int reg;
167 	u32 val;
168 };
169 
170 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS	2
171 struct rockchip_cpuclk_rate_table {
172 	unsigned long prate;
173 	struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
174 };
175 
176 /**
177  * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
178  * @core_reg:		register offset of the core settings register
179  * @div_core_shift:	core divider offset used to divide the pll value
180  * @div_core_mask:	core divider mask
181  * @mux_core_shift:	offset of the core multiplexer
182  */
183 struct rockchip_cpuclk_reg_data {
184 	int		core_reg;
185 	u8		div_core_shift;
186 	u32		div_core_mask;
187 	int		mux_core_reg;
188 	u8		mux_core_shift;
189 };
190 
191 struct clk *rockchip_clk_register_cpuclk(const char *name,
192 			const char *const *parent_names, u8 num_parents,
193 			const struct rockchip_cpuclk_reg_data *reg_data,
194 			const struct rockchip_cpuclk_rate_table *rates,
195 			int nrates, void __iomem *reg_base, spinlock_t *lock);
196 
197 struct clk *rockchip_clk_register_mmc(const char *name,
198 				const char *const *parent_names, u8 num_parents,
199 				void __iomem *reg, int shift);
200 
201 #define ROCKCHIP_INVERTER_HIWORD_MASK	BIT(0)
202 
203 struct clk *rockchip_clk_register_inverter(const char *name,
204 				const char *const *parent_names, u8 num_parents,
205 				void __iomem *reg, int shift, int flags,
206 				spinlock_t *lock);
207 
208 #define PNAME(x) static const char *const x[] __initconst
209 
210 enum rockchip_clk_branch_type {
211 	branch_composite,
212 	branch_mux,
213 	branch_divider,
214 	branch_fraction_divider,
215 	branch_gate,
216 	branch_mmc,
217 	branch_inverter,
218 };
219 
220 struct rockchip_clk_branch {
221 	unsigned int			id;
222 	enum rockchip_clk_branch_type	branch_type;
223 	const char			*name;
224 	const char			*const *parent_names;
225 	u8				num_parents;
226 	unsigned long			flags;
227 	int				muxdiv_offset;
228 	u8				mux_shift;
229 	u8				mux_width;
230 	u8				mux_flags;
231 	u8				div_shift;
232 	u8				div_width;
233 	u8				div_flags;
234 	struct clk_div_table		*div_table;
235 	int				gate_offset;
236 	u8				gate_shift;
237 	u8				gate_flags;
238 };
239 
240 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
241 		  df, go, gs, gf)				\
242 	{							\
243 		.id		= _id,				\
244 		.branch_type	= branch_composite,		\
245 		.name		= cname,			\
246 		.parent_names	= pnames,			\
247 		.num_parents	= ARRAY_SIZE(pnames),		\
248 		.flags		= f,				\
249 		.muxdiv_offset	= mo,				\
250 		.mux_shift	= ms,				\
251 		.mux_width	= mw,				\
252 		.mux_flags	= mf,				\
253 		.div_shift	= ds,				\
254 		.div_width	= dw,				\
255 		.div_flags	= df,				\
256 		.gate_offset	= go,				\
257 		.gate_shift	= gs,				\
258 		.gate_flags	= gf,				\
259 	}
260 
261 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df,	\
262 			go, gs, gf)				\
263 	{							\
264 		.id		= _id,				\
265 		.branch_type	= branch_composite,		\
266 		.name		= cname,			\
267 		.parent_names	= (const char *[]){ pname },	\
268 		.num_parents	= 1,				\
269 		.flags		= f,				\
270 		.muxdiv_offset	= mo,				\
271 		.div_shift	= ds,				\
272 		.div_width	= dw,				\
273 		.div_flags	= df,				\
274 		.gate_offset	= go,				\
275 		.gate_shift	= gs,				\
276 		.gate_flags	= gf,				\
277 	}
278 
279 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
280 			       df, dt, go, gs, gf)		\
281 	{							\
282 		.id		= _id,				\
283 		.branch_type	= branch_composite,		\
284 		.name		= cname,			\
285 		.parent_names	= (const char *[]){ pname },	\
286 		.num_parents	= 1,				\
287 		.flags		= f,				\
288 		.muxdiv_offset	= mo,				\
289 		.div_shift	= ds,				\
290 		.div_width	= dw,				\
291 		.div_flags	= df,				\
292 		.div_table	= dt,				\
293 		.gate_offset	= go,				\
294 		.gate_shift	= gs,				\
295 		.gate_flags	= gf,				\
296 	}
297 
298 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf,	\
299 			go, gs, gf)				\
300 	{							\
301 		.id		= _id,				\
302 		.branch_type	= branch_composite,		\
303 		.name		= cname,			\
304 		.parent_names	= pnames,			\
305 		.num_parents	= ARRAY_SIZE(pnames),		\
306 		.flags		= f,				\
307 		.muxdiv_offset	= mo,				\
308 		.mux_shift	= ms,				\
309 		.mux_width	= mw,				\
310 		.mux_flags	= mf,				\
311 		.gate_offset	= go,				\
312 		.gate_shift	= gs,				\
313 		.gate_flags	= gf,				\
314 	}
315 
316 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf,	\
317 			 ds, dw, df)				\
318 	{							\
319 		.id		= _id,				\
320 		.branch_type	= branch_composite,		\
321 		.name		= cname,			\
322 		.parent_names	= pnames,			\
323 		.num_parents	= ARRAY_SIZE(pnames),		\
324 		.flags		= f,				\
325 		.muxdiv_offset	= mo,				\
326 		.mux_shift	= ms,				\
327 		.mux_width	= mw,				\
328 		.mux_flags	= mf,				\
329 		.div_shift	= ds,				\
330 		.div_width	= dw,				\
331 		.div_flags	= df,				\
332 		.gate_offset	= -1,				\
333 	}
334 
335 #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms,	\
336 				mw, mf, ds, dw, df, dt)		\
337 	{							\
338 		.id		= _id,				\
339 		.branch_type	= branch_composite,		\
340 		.name		= cname,			\
341 		.parent_names	= pnames,			\
342 		.num_parents	= ARRAY_SIZE(pnames),		\
343 		.flags		= f,				\
344 		.muxdiv_offset	= mo,				\
345 		.mux_shift	= ms,				\
346 		.mux_width	= mw,				\
347 		.mux_flags	= mf,				\
348 		.div_shift	= ds,				\
349 		.div_width	= dw,				\
350 		.div_flags	= df,				\
351 		.div_table	= dt,				\
352 		.gate_offset	= -1,				\
353 	}
354 
355 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
356 	{							\
357 		.id		= _id,				\
358 		.branch_type	= branch_fraction_divider,	\
359 		.name		= cname,			\
360 		.parent_names	= (const char *[]){ pname },	\
361 		.num_parents	= 1,				\
362 		.flags		= f,				\
363 		.muxdiv_offset	= mo,				\
364 		.div_shift	= 16,				\
365 		.div_width	= 16,				\
366 		.div_flags	= df,				\
367 		.gate_offset	= go,				\
368 		.gate_shift	= gs,				\
369 		.gate_flags	= gf,				\
370 	}
371 
372 #define MUX(_id, cname, pnames, f, o, s, w, mf)			\
373 	{							\
374 		.id		= _id,				\
375 		.branch_type	= branch_mux,			\
376 		.name		= cname,			\
377 		.parent_names	= pnames,			\
378 		.num_parents	= ARRAY_SIZE(pnames),		\
379 		.flags		= f,				\
380 		.muxdiv_offset	= o,				\
381 		.mux_shift	= s,				\
382 		.mux_width	= w,				\
383 		.mux_flags	= mf,				\
384 		.gate_offset	= -1,				\
385 	}
386 
387 #define DIV(_id, cname, pname, f, o, s, w, df)			\
388 	{							\
389 		.id		= _id,				\
390 		.branch_type	= branch_divider,		\
391 		.name		= cname,			\
392 		.parent_names	= (const char *[]){ pname },	\
393 		.num_parents	= 1,				\
394 		.flags		= f,				\
395 		.muxdiv_offset	= o,				\
396 		.div_shift	= s,				\
397 		.div_width	= w,				\
398 		.div_flags	= df,				\
399 		.gate_offset	= -1,				\
400 	}
401 
402 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt)		\
403 	{							\
404 		.id		= _id,				\
405 		.branch_type	= branch_divider,		\
406 		.name		= cname,			\
407 		.parent_names	= (const char *[]){ pname },	\
408 		.num_parents	= 1,				\
409 		.flags		= f,				\
410 		.muxdiv_offset	= o,				\
411 		.div_shift	= s,				\
412 		.div_width	= w,				\
413 		.div_flags	= df,				\
414 		.div_table	= dt,				\
415 	}
416 
417 #define GATE(_id, cname, pname, f, o, b, gf)			\
418 	{							\
419 		.id		= _id,				\
420 		.branch_type	= branch_gate,			\
421 		.name		= cname,			\
422 		.parent_names	= (const char *[]){ pname },	\
423 		.num_parents	= 1,				\
424 		.flags		= f,				\
425 		.gate_offset	= o,				\
426 		.gate_shift	= b,				\
427 		.gate_flags	= gf,				\
428 	}
429 
430 #define MMC(_id, cname, pname, offset, shift)			\
431 	{							\
432 		.id		= _id,				\
433 		.branch_type	= branch_mmc,			\
434 		.name		= cname,			\
435 		.parent_names	= (const char *[]){ pname },	\
436 		.num_parents	= 1,				\
437 		.muxdiv_offset	= offset,			\
438 		.div_shift	= shift,			\
439 	}
440 
441 #define INVERTER(_id, cname, pname, io, is, if)			\
442 	{							\
443 		.id		= _id,				\
444 		.branch_type	= branch_inverter,		\
445 		.name		= cname,			\
446 		.parent_names	= (const char *[]){ pname },	\
447 		.num_parents	= 1,				\
448 		.muxdiv_offset	= io,				\
449 		.div_shift	= is,				\
450 		.div_flags	= if,				\
451 	}
452 
453 void rockchip_clk_init(struct device_node *np, void __iomem *base,
454 		       unsigned long nr_clks);
455 struct regmap *rockchip_clk_get_grf(void);
456 void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
457 void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
458 				    unsigned int nr_clk);
459 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
460 				unsigned int nr_pll, int grf_lock_offset);
461 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
462 			const char *const *parent_names, u8 num_parents,
463 			const struct rockchip_cpuclk_reg_data *reg_data,
464 			const struct rockchip_cpuclk_rate_table *rates,
465 			int nrates);
466 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
467 void rockchip_register_restart_notifier(unsigned int reg);
468 
469 #define ROCKCHIP_SOFTRST_HIWORD_MASK	BIT(0)
470 
471 #ifdef CONFIG_RESET_CONTROLLER
472 void rockchip_register_softrst(struct device_node *np,
473 			       unsigned int num_regs,
474 			       void __iomem *base, u8 flags);
475 #else
476 static inline void rockchip_register_softrst(struct device_node *np,
477 			       unsigned int num_regs,
478 			       void __iomem *base, u8 flags)
479 {
480 }
481 #endif
482 
483 #endif
484