2 * Copyright (c) 2014 MundoReader S.L.
3 * Author: Heiko Stuebner <heiko@sntech.de>
8 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
9 * Copyright (c) 2013 Linaro Ltd.
10 * Author: Thomas Abraham <thomas.ab@samsung.com>
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.
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.
23 #ifndef CLK_ROCKCHIP_CLK_H
24 #define CLK_ROCKCHIP_CLK_H
27 #include <linux/clk.h>
28 #include <linux/clk-provider.h>
30 #define HIWORD_UPDATE(val, mask, shift) \
31 ((val) << (shift) | (mask) << ((shift) + 16))
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
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
60 enum rockchip_pll_type
{
64 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
70 .bwadj = (_nf >> 1), \
73 #define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \
82 struct rockchip_pll_rate_table
{
91 * struct rockchip_pll_clock: information about pll clock
92 * @id: platform specific id of the clock.
93 * @name: name of this pll clock.
94 * @parent_name: name of the parent clock.
95 * @flags: optional flags for basic clock.
96 * @con_offset: offset of the register for configuring the PLL.
97 * @mode_offset: offset of the register for configuring the PLL-mode.
98 * @mode_shift: offset inside the mode-register for the mode of this pll.
99 * @lock_shift: offset inside the lock register for the lock status.
100 * @type: Type of PLL to be registered.
101 * @pll_flags: hardware-specific flags
102 * @rate_table: Table of usable pll rates
105 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
106 * rate_table parameters and ajust them if necessary.
108 struct rockchip_pll_clock
{
111 const char **parent_names
;
118 enum rockchip_pll_type type
;
120 struct rockchip_pll_rate_table
*rate_table
;
123 #define ROCKCHIP_PLL_SYNC_RATE BIT(0)
125 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \
126 _lshift, _pflags, _rtable) \
131 .parent_names = _pnames, \
132 .num_parents = ARRAY_SIZE(_pnames), \
133 .flags = CLK_GET_RATE_NOCACHE | _flags, \
134 .con_offset = _con, \
135 .mode_offset = _mode, \
136 .mode_shift = _mshift, \
137 .lock_shift = _lshift, \
138 .pll_flags = _pflags, \
139 .rate_table = _rtable, \
142 struct clk
*rockchip_clk_register_pll(enum rockchip_pll_type pll_type
,
143 const char *name
, const char **parent_names
, u8 num_parents
,
144 void __iomem
*base
, int con_offset
, int grf_lock_offset
,
145 int lock_shift
, int reg_mode
, int mode_shift
,
146 struct rockchip_pll_rate_table
*rate_table
,
147 u8 clk_pll_flags
, spinlock_t
*lock
);
149 struct rockchip_cpuclk_clksel
{
154 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
155 struct rockchip_cpuclk_rate_table
{
157 struct rockchip_cpuclk_clksel divs
[ROCKCHIP_CPUCLK_NUM_DIVIDERS
];
161 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
162 * @core_reg: register offset of the core settings register
163 * @div_core_shift: core divider offset used to divide the pll value
164 * @div_core_mask: core divider mask
165 * @mux_core_shift: offset of the core multiplexer
167 struct rockchip_cpuclk_reg_data
{
175 struct clk
*rockchip_clk_register_cpuclk(const char *name
,
176 const char **parent_names
, u8 num_parents
,
177 const struct rockchip_cpuclk_reg_data
*reg_data
,
178 const struct rockchip_cpuclk_rate_table
*rates
,
179 int nrates
, void __iomem
*reg_base
, spinlock_t
*lock
);
181 struct clk
*rockchip_clk_register_mmc(const char *name
,
182 const char **parent_names
, u8 num_parents
,
183 void __iomem
*reg
, int shift
);
185 #define PNAME(x) static const char *x[] __initdata
187 enum rockchip_clk_branch_type
{
191 branch_fraction_divider
,
196 struct rockchip_clk_branch
{
198 enum rockchip_clk_branch_type branch_type
;
200 const char **parent_names
;
210 struct clk_div_table
*div_table
;
216 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
220 .branch_type = branch_composite, \
222 .parent_names = pnames, \
223 .num_parents = ARRAY_SIZE(pnames), \
225 .muxdiv_offset = mo, \
237 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
241 .branch_type = branch_composite, \
243 .parent_names = (const char *[]){ pname }, \
246 .muxdiv_offset = mo, \
255 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
256 df, dt, go, gs, gf) \
259 .branch_type = branch_composite, \
261 .parent_names = (const char *[]){ pname }, \
264 .muxdiv_offset = mo, \
274 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \
278 .branch_type = branch_composite, \
280 .parent_names = pnames, \
281 .num_parents = ARRAY_SIZE(pnames), \
283 .muxdiv_offset = mo, \
292 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
296 .branch_type = branch_composite, \
298 .parent_names = pnames, \
299 .num_parents = ARRAY_SIZE(pnames), \
301 .muxdiv_offset = mo, \
311 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
314 .branch_type = branch_fraction_divider, \
316 .parent_names = (const char *[]){ pname }, \
319 .muxdiv_offset = mo, \
328 #define MUX(_id, cname, pnames, f, o, s, w, mf) \
331 .branch_type = branch_mux, \
333 .parent_names = pnames, \
334 .num_parents = ARRAY_SIZE(pnames), \
336 .muxdiv_offset = o, \
343 #define DIV(_id, cname, pname, f, o, s, w, df) \
346 .branch_type = branch_divider, \
348 .parent_names = (const char *[]){ pname }, \
351 .muxdiv_offset = o, \
358 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
361 .branch_type = branch_divider, \
363 .parent_names = (const char *[]){ pname }, \
366 .muxdiv_offset = o, \
373 #define GATE(_id, cname, pname, f, o, b, gf) \
376 .branch_type = branch_gate, \
378 .parent_names = (const char *[]){ pname }, \
386 #define MMC(_id, cname, pname, offset, shift) \
389 .branch_type = branch_mmc, \
391 .parent_names = (const char *[]){ pname }, \
393 .muxdiv_offset = offset, \
394 .div_shift = shift, \
397 void rockchip_clk_init(struct device_node
*np
, void __iomem
*base
,
398 unsigned long nr_clks
);
399 struct regmap
*rockchip_clk_get_grf(void);
400 void rockchip_clk_add_lookup(struct clk
*clk
, unsigned int id
);
401 void rockchip_clk_register_branches(struct rockchip_clk_branch
*clk_list
,
402 unsigned int nr_clk
);
403 void rockchip_clk_register_plls(struct rockchip_pll_clock
*pll_list
,
404 unsigned int nr_pll
, int grf_lock_offset
);
405 void rockchip_clk_register_armclk(unsigned int lookup_id
, const char *name
,
406 const char **parent_names
, u8 num_parents
,
407 const struct rockchip_cpuclk_reg_data
*reg_data
,
408 const struct rockchip_cpuclk_rate_table
*rates
,
410 void rockchip_clk_protect_critical(const char *const clocks
[], int nclocks
);
411 void rockchip_register_restart_notifier(unsigned int reg
);
413 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
415 #ifdef CONFIG_RESET_CONTROLLER
416 void rockchip_register_softrst(struct device_node
*np
,
417 unsigned int num_regs
,
418 void __iomem
*base
, u8 flags
);
420 static inline void rockchip_register_softrst(struct device_node
*np
,
421 unsigned int num_regs
,
422 void __iomem
*base
, u8 flags
)