blob: 6b53fff4cc96b6d2b875c5e4e94e32c7ca3d632b [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 *
Xing Zheng9c4d6e52015-11-05 15:33:57 +08005 * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
6 * Author: Xing Zheng <zhengxing@rock-chips.com>
7 *
Heiko Stübnera245fec2014-07-03 01:58:39 +02008 * based on
9 *
10 * samsung/clk.h
11 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
12 * Copyright (c) 2013 Linaro Ltd.
13 * Author: Thomas Abraham <thomas.ab@samsung.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 */
25
26#ifndef CLK_ROCKCHIP_CLK_H
27#define CLK_ROCKCHIP_CLK_H
28
29#include <linux/io.h>
Xing Zhengef1d9fe2016-03-09 10:37:04 +080030#include <linux/clk-provider.h>
Stephen Boydf684ff82015-06-19 15:00:46 -070031
32struct clk;
Heiko Stübnera245fec2014-07-03 01:58:39 +020033
34#define HIWORD_UPDATE(val, mask, shift) \
35 ((val) << (shift) | (mask) << ((shift) + 16))
36
Elaine Zhang243229b2018-06-15 10:16:51 +080037/* register positions shared by PX30, RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
38#define BOOST_PLL_H_CON(x) ((x) * 0x4)
39#define BOOST_CLK_CON 0x0008
40#define BOOST_BOOST_CON 0x000c
41#define BOOST_SWITCH_CNT 0x0010
42#define BOOST_HIGH_PERF_CNT0 0x0014
43#define BOOST_HIGH_PERF_CNT1 0x0018
44#define BOOST_STATIS_THRESHOLD 0x001c
45#define BOOST_SHORT_SWITCH_CNT 0x0020
46#define BOOST_SWITCH_THRESHOLD 0x0024
47#define BOOST_FSM_STATUS 0x0028
48#define BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x2c)
49#define BOOST_RECOVERY_MASK 0x1
50#define BOOST_RECOVERY_SHIFT 1
51#define BOOST_SW_CTRL_MASK 0x1
52#define BOOST_SW_CTRL_SHIFT 2
53#define BOOST_LOW_FREQ_EN_MASK 0x1
54#define BOOST_LOW_FREQ_EN_SHIFT 3
55#define BOOST_BUSY_STATE BIT(8)
56
57#define PX30_PLL_CON(x) ((x) * 0x4)
58#define PX30_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
59#define PX30_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
60#define PX30_GLB_SRST_FST 0xb8
61#define PX30_GLB_SRST_SND 0xbc
62#define PX30_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
63#define PX30_MODE_CON 0xa0
64#define PX30_MISC_CON 0xa4
65#define PX30_SDMMC_CON0 0x380
66#define PX30_SDMMC_CON1 0x384
67#define PX30_SDIO_CON0 0x388
68#define PX30_SDIO_CON1 0x38c
69#define PX30_EMMC_CON0 0x390
70#define PX30_EMMC_CON1 0x394
71
72#define PX30_PMU_PLL_CON(x) ((x) * 0x4)
73#define PX30_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x40)
74#define PX30_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x80)
75#define PX30_PMU_MODE 0x0020
76
Andy Yan7e2a9032017-03-17 18:18:38 +010077#define RV1108_PLL_CON(x) ((x) * 0x4)
78#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
79#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
80#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
81#define RV1108_GLB_SRST_FST 0x1c0
82#define RV1108_GLB_SRST_SND 0x1c4
83#define RV1108_MISC_CON 0x1cc
84#define RV1108_SDMMC_CON0 0x1d8
85#define RV1108_SDMMC_CON1 0x1dc
86#define RV1108_SDIO_CON0 0x1e0
87#define RV1108_SDIO_CON1 0x1e4
88#define RV1108_EMMC_CON0 0x1e8
89#define RV1108_EMMC_CON1 0x1ec
Shawn Line44dde22016-11-16 16:49:23 +080090
Heiko Stuebner2d7884a2015-06-18 16:18:30 +020091#define RK2928_PLL_CON(x) ((x) * 0x4)
Heiko Stübnera245fec2014-07-03 01:58:39 +020092#define RK2928_MODE_CON 0x40
Heiko Stuebner2d7884a2015-06-18 16:18:30 +020093#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)
94#define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0)
Heiko Stübnera245fec2014-07-03 01:58:39 +020095#define RK2928_GLB_SRST_FST 0x100
96#define RK2928_GLB_SRST_SND 0x104
Heiko Stuebner2d7884a2015-06-18 16:18:30 +020097#define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110)
Heiko Stübnera245fec2014-07-03 01:58:39 +020098#define RK2928_MISC_CON 0x134
99
Xing Zheng5190c082015-11-05 15:33:58 +0800100#define RK3036_SDMMC_CON0 0x144
101#define RK3036_SDMMC_CON1 0x148
102#define RK3036_SDIO_CON0 0x14c
103#define RK3036_SDIO_CON1 0x150
104#define RK3036_EMMC_CON0 0x154
105#define RK3036_EMMC_CON1 0x158
106
Jeffy Chen307a2e92015-12-11 09:30:50 +0800107#define RK3228_GLB_SRST_FST 0x1f0
108#define RK3228_GLB_SRST_SND 0x1f4
109#define RK3228_SDMMC_CON0 0x1c0
110#define RK3228_SDMMC_CON1 0x1c4
111#define RK3228_SDIO_CON0 0x1c8
112#define RK3228_SDIO_CON1 0x1cc
113#define RK3228_EMMC_CON0 0x1d8
114#define RK3228_EMMC_CON1 0x1dc
115
Heiko Stübnerb9e4ba52014-07-03 02:02:37 +0200116#define RK3288_PLL_CON(x) RK2928_PLL_CON(x)
117#define RK3288_MODE_CON 0x50
Heiko Stuebner2d7884a2015-06-18 16:18:30 +0200118#define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
119#define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160)
Heiko Stübnerb9e4ba52014-07-03 02:02:37 +0200120#define RK3288_GLB_SRST_FST 0x1b0
121#define RK3288_GLB_SRST_SND 0x1b4
Heiko Stuebner2d7884a2015-06-18 16:18:30 +0200122#define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8)
Heiko Stübnerb9e4ba52014-07-03 02:02:37 +0200123#define RK3288_MISC_CON 0x1e8
Alexandru M Stan89bf26c2014-11-26 17:30:27 -0800124#define RK3288_SDMMC_CON0 0x200
125#define RK3288_SDMMC_CON1 0x204
126#define RK3288_SDIO0_CON0 0x208
127#define RK3288_SDIO0_CON1 0x20c
128#define RK3288_SDIO1_CON0 0x210
129#define RK3288_SDIO1_CON1 0x214
130#define RK3288_EMMC_CON0 0x218
131#define RK3288_EMMC_CON1 0x21c
Heiko Stübnerb9e4ba52014-07-03 02:02:37 +0200132
Elaine Zhangfe3511a2016-12-29 10:45:11 +0800133#define RK3328_PLL_CON(x) RK2928_PLL_CON(x)
134#define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
135#define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
136#define RK3328_GRFCLKSEL_CON(x) ((x) * 0x4 + 0x100)
137#define RK3328_GLB_SRST_FST 0x9c
138#define RK3328_GLB_SRST_SND 0x98
139#define RK3328_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
140#define RK3328_MODE_CON 0x80
141#define RK3328_MISC_CON 0x84
142#define RK3328_SDMMC_CON0 0x380
143#define RK3328_SDMMC_CON1 0x384
144#define RK3328_SDIO_CON0 0x388
145#define RK3328_SDIO_CON1 0x38c
146#define RK3328_EMMC_CON0 0x390
147#define RK3328_EMMC_CON1 0x394
148#define RK3328_SDMMC_EXT_CON0 0x398
149#define RK3328_SDMMC_EXT_CON1 0x39C
150
Heiko Stuebner3536c972015-07-05 11:00:20 +0200151#define RK3368_PLL_CON(x) RK2928_PLL_CON(x)
152#define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
153#define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
154#define RK3368_GLB_SRST_FST 0x280
155#define RK3368_GLB_SRST_SND 0x284
156#define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
157#define RK3368_MISC_CON 0x380
158#define RK3368_SDMMC_CON0 0x400
159#define RK3368_SDMMC_CON1 0x404
160#define RK3368_SDIO0_CON0 0x408
161#define RK3368_SDIO0_CON1 0x40c
162#define RK3368_SDIO1_CON0 0x410
163#define RK3368_SDIO1_CON1 0x414
164#define RK3368_EMMC_CON0 0x418
165#define RK3368_EMMC_CON1 0x41c
166
Xing Zheng11551002016-03-28 17:51:37 +0800167#define RK3399_PLL_CON(x) RK2928_PLL_CON(x)
168#define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
169#define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300)
170#define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400)
171#define RK3399_GLB_SRST_FST 0x500
172#define RK3399_GLB_SRST_SND 0x504
173#define RK3399_GLB_CNT_TH 0x508
174#define RK3399_MISC_CON 0x50c
175#define RK3399_RST_CON 0x510
176#define RK3399_RST_ST 0x514
177#define RK3399_SDMMC_CON0 0x580
178#define RK3399_SDMMC_CON1 0x584
179#define RK3399_SDIO_CON0 0x588
180#define RK3399_SDIO_CON1 0x58c
181
182#define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x)
183#define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80)
184#define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100)
185#define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110)
186
Heiko Stübner90c59022014-07-03 01:59:10 +0200187enum rockchip_pll_type {
Xing Zheng9c4d6e52015-11-05 15:33:57 +0800188 pll_rk3036,
Heiko Stübner90c59022014-07-03 01:59:10 +0200189 pll_rk3066,
Elaine Zhang7bed9242016-12-29 10:45:10 +0800190 pll_rk3328,
Xing Zhengb40bacc2016-03-10 11:47:01 +0800191 pll_rk3399,
Heiko Stübner90c59022014-07-03 01:59:10 +0200192};
193
Xing Zheng9c4d6e52015-11-05 15:33:57 +0800194#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
195 _postdiv2, _dsmpd, _frac) \
196{ \
197 .rate = _rate##U, \
198 .fbdiv = _fbdiv, \
199 .postdiv1 = _postdiv1, \
200 .refdiv = _refdiv, \
201 .postdiv2 = _postdiv2, \
202 .dsmpd = _dsmpd, \
203 .frac = _frac, \
204}
205
Heiko Stübner90c59022014-07-03 01:59:10 +0200206#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
207{ \
208 .rate = _rate##U, \
209 .nr = _nr, \
210 .nf = _nf, \
211 .no = _no, \
Douglas Anderson2bbfe002015-07-21 13:41:23 -0700212 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \
Heiko Stübner90c59022014-07-03 01:59:10 +0200213}
214
Douglas Anderson2bbfe002015-07-21 13:41:23 -0700215#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \
Kever Yang49ed9ee2014-10-09 22:23:57 -0700216{ \
217 .rate = _rate##U, \
218 .nr = _nr, \
219 .nf = _nf, \
220 .no = _no, \
Douglas Anderson2bbfe002015-07-21 13:41:23 -0700221 .nb = _nb, \
Kever Yang49ed9ee2014-10-09 22:23:57 -0700222}
223
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800224/**
Shawn Lin2af25442016-03-13 00:25:14 +0800225 * struct rockchip_clk_provider - information about clock provider
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800226 * @reg_base: virtual address for the register base.
227 * @clk_data: holds clock related data like clk* and number of clocks.
228 * @cru_node: device-node of the clock-provider
229 * @grf: regmap of the general-register-files syscon
230 * @lock: maintains exclusion between callbacks for a given clock-provider.
231 */
232struct rockchip_clk_provider {
233 void __iomem *reg_base;
234 struct clk_onecell_data clk_data;
235 struct device_node *cru_node;
236 struct regmap *grf;
237 spinlock_t lock;
238};
239
Heiko Stübner90c59022014-07-03 01:59:10 +0200240struct rockchip_pll_rate_table {
241 unsigned long rate;
242 unsigned int nr;
243 unsigned int nf;
244 unsigned int no;
Douglas Anderson2bbfe002015-07-21 13:41:23 -0700245 unsigned int nb;
Xing Zhengb40bacc2016-03-10 11:47:01 +0800246 /* for RK3036/RK3399 */
Xing Zheng9c4d6e52015-11-05 15:33:57 +0800247 unsigned int fbdiv;
248 unsigned int postdiv1;
249 unsigned int refdiv;
250 unsigned int postdiv2;
251 unsigned int dsmpd;
252 unsigned int frac;
Heiko Stübner90c59022014-07-03 01:59:10 +0200253};
254
255/**
Shawn Lin2af25442016-03-13 00:25:14 +0800256 * struct rockchip_pll_clock - information about pll clock
Heiko Stübner90c59022014-07-03 01:59:10 +0200257 * @id: platform specific id of the clock.
258 * @name: name of this pll clock.
Shawn Lin2af25442016-03-13 00:25:14 +0800259 * @parent_names: name of the parent clock.
260 * @num_parents: number of parents
Heiko Stübner90c59022014-07-03 01:59:10 +0200261 * @flags: optional flags for basic clock.
262 * @con_offset: offset of the register for configuring the PLL.
263 * @mode_offset: offset of the register for configuring the PLL-mode.
264 * @mode_shift: offset inside the mode-register for the mode of this pll.
265 * @lock_shift: offset inside the lock register for the lock status.
266 * @type: Type of PLL to be registered.
Heiko Stuebner4f8a7c52014-11-20 20:38:50 +0100267 * @pll_flags: hardware-specific flags
Heiko Stübner90c59022014-07-03 01:59:10 +0200268 * @rate_table: Table of usable pll rates
Heiko Stuebner0bb66d32014-11-20 20:38:52 +0100269 *
270 * Flags:
271 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
272 * rate_table parameters and ajust them if necessary.
Heiko Stübner90c59022014-07-03 01:59:10 +0200273 */
274struct rockchip_pll_clock {
275 unsigned int id;
276 const char *name;
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200277 const char *const *parent_names;
Heiko Stübner90c59022014-07-03 01:59:10 +0200278 u8 num_parents;
279 unsigned long flags;
280 int con_offset;
281 int mode_offset;
282 int mode_shift;
283 int lock_shift;
284 enum rockchip_pll_type type;
Heiko Stuebner4f8a7c52014-11-20 20:38:50 +0100285 u8 pll_flags;
Heiko Stübner90c59022014-07-03 01:59:10 +0200286 struct rockchip_pll_rate_table *rate_table;
287};
288
Heiko Stuebner0bb66d32014-11-20 20:38:52 +0100289#define ROCKCHIP_PLL_SYNC_RATE BIT(0)
290
Heiko Stübner90c59022014-07-03 01:59:10 +0200291#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \
Heiko Stuebner4f8a7c52014-11-20 20:38:50 +0100292 _lshift, _pflags, _rtable) \
Heiko Stübner90c59022014-07-03 01:59:10 +0200293 { \
294 .id = _id, \
295 .type = _type, \
296 .name = _name, \
297 .parent_names = _pnames, \
298 .num_parents = ARRAY_SIZE(_pnames), \
299 .flags = CLK_GET_RATE_NOCACHE | _flags, \
300 .con_offset = _con, \
301 .mode_offset = _mode, \
302 .mode_shift = _mshift, \
303 .lock_shift = _lshift, \
Heiko Stuebner4f8a7c52014-11-20 20:38:50 +0100304 .pll_flags = _pflags, \
Heiko Stübner90c59022014-07-03 01:59:10 +0200305 .rate_table = _rtable, \
306 }
307
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800308struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
309 enum rockchip_pll_type pll_type,
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200310 const char *name, const char *const *parent_names,
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800311 u8 num_parents, int con_offset, int grf_lock_offset,
312 int lock_shift, int mode_offset, int mode_shift,
313 struct rockchip_pll_rate_table *rate_table,
Heiko Stübnere6cebc72016-07-29 15:56:55 +0800314 unsigned long flags, u8 clk_pll_flags);
Heiko Stübner90c59022014-07-03 01:59:10 +0200315
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200316struct rockchip_cpuclk_clksel {
317 int reg;
318 u32 val;
319};
320
321#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
322struct rockchip_cpuclk_rate_table {
323 unsigned long prate;
324 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
325};
326
327/**
Heiko Stuebner03ae1742016-04-19 21:29:27 +0200328 * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200329 * @core_reg: register offset of the core settings register
330 * @div_core_shift: core divider offset used to divide the pll value
331 * @div_core_mask: core divider mask
Xing Zheng268aeba2016-03-09 10:37:03 +0800332 * @mux_core_alt: mux value to select alternate parent
333 * @mux_core_main: mux value to select main parent of core
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200334 * @mux_core_shift: offset of the core multiplexer
Xing Zheng268aeba2016-03-09 10:37:03 +0800335 * @mux_core_mask: core multiplexer mask
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200336 */
337struct rockchip_cpuclk_reg_data {
338 int core_reg;
339 u8 div_core_shift;
340 u32 div_core_mask;
Xing Zheng268aeba2016-03-09 10:37:03 +0800341 u8 mux_core_alt;
342 u8 mux_core_main;
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200343 u8 mux_core_shift;
Xing Zheng268aeba2016-03-09 10:37:03 +0800344 u32 mux_core_mask;
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200345};
346
347struct clk *rockchip_clk_register_cpuclk(const char *name,
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200348 const char *const *parent_names, u8 num_parents,
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200349 const struct rockchip_cpuclk_reg_data *reg_data,
350 const struct rockchip_cpuclk_rate_table *rates,
351 int nrates, void __iomem *reg_base, spinlock_t *lock);
352
Alexandru M Stan89bf26c2014-11-26 17:30:27 -0800353struct clk *rockchip_clk_register_mmc(const char *name,
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200354 const char *const *parent_names, u8 num_parents,
Alexandru M Stan89bf26c2014-11-26 17:30:27 -0800355 void __iomem *reg, int shift);
356
Lin Huanga4f182b2016-08-22 11:36:17 +0800357/*
358 * DDRCLK flags, including method of setting the rate
359 * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate.
360 */
361#define ROCKCHIP_DDRCLK_SIP BIT(0)
362
363struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
364 const char *const *parent_names,
365 u8 num_parents, int mux_offset,
366 int mux_shift, int mux_width,
367 int div_shift, int div_width,
368 int ddr_flags, void __iomem *reg_base,
369 spinlock_t *lock);
370
Heiko Stuebner8a76f442015-07-05 11:00:14 +0200371#define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0)
372
373struct clk *rockchip_clk_register_inverter(const char *name,
374 const char *const *parent_names, u8 num_parents,
375 void __iomem *reg, int shift, int flags,
376 spinlock_t *lock);
377
Heiko Stuebnercb1d9f62016-12-27 00:00:38 +0100378struct clk *rockchip_clk_register_muxgrf(const char *name,
379 const char *const *parent_names, u8 num_parents,
380 int flags, struct regmap *grf, int reg,
381 int shift, int width, int mux_flags);
382
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200383#define PNAME(x) static const char *const x[] __initconst
Heiko Stübnera245fec2014-07-03 01:58:39 +0200384
385enum rockchip_clk_branch_type {
386 branch_composite,
387 branch_mux,
Heiko Stuebnercb1d9f62016-12-27 00:00:38 +0100388 branch_muxgrf,
Heiko Stübnera245fec2014-07-03 01:58:39 +0200389 branch_divider,
390 branch_fraction_divider,
391 branch_gate,
Alexandru M Stan89bf26c2014-11-26 17:30:27 -0800392 branch_mmc,
Heiko Stuebner8a76f442015-07-05 11:00:14 +0200393 branch_inverter,
Heiko Stuebner29a30c22015-06-20 13:08:57 +0200394 branch_factor,
Lin Huanga4f182b2016-08-22 11:36:17 +0800395 branch_ddrclk,
Elaine Zhang956060a2018-06-15 10:16:50 +0800396 branch_half_divider,
Heiko Stübnera245fec2014-07-03 01:58:39 +0200397};
398
399struct rockchip_clk_branch {
400 unsigned int id;
401 enum rockchip_clk_branch_type branch_type;
402 const char *name;
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200403 const char *const *parent_names;
Heiko Stübnera245fec2014-07-03 01:58:39 +0200404 u8 num_parents;
405 unsigned long flags;
406 int muxdiv_offset;
407 u8 mux_shift;
408 u8 mux_width;
409 u8 mux_flags;
410 u8 div_shift;
411 u8 div_width;
412 u8 div_flags;
413 struct clk_div_table *div_table;
414 int gate_offset;
415 u8 gate_shift;
416 u8 gate_flags;
Heiko Stuebner8ca1ca82015-12-22 22:27:59 +0100417 struct rockchip_clk_branch *child;
Heiko Stübnera245fec2014-07-03 01:58:39 +0200418};
419
420#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
421 df, go, gs, gf) \
422 { \
423 .id = _id, \
424 .branch_type = branch_composite, \
425 .name = cname, \
426 .parent_names = pnames, \
427 .num_parents = ARRAY_SIZE(pnames), \
428 .flags = f, \
429 .muxdiv_offset = mo, \
430 .mux_shift = ms, \
431 .mux_width = mw, \
432 .mux_flags = mf, \
433 .div_shift = ds, \
434 .div_width = dw, \
435 .div_flags = df, \
436 .gate_offset = go, \
437 .gate_shift = gs, \
438 .gate_flags = gf, \
439 }
440
441#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
442 go, gs, gf) \
443 { \
444 .id = _id, \
445 .branch_type = branch_composite, \
446 .name = cname, \
447 .parent_names = (const char *[]){ pname }, \
448 .num_parents = 1, \
449 .flags = f, \
450 .muxdiv_offset = mo, \
451 .div_shift = ds, \
452 .div_width = dw, \
453 .div_flags = df, \
454 .gate_offset = go, \
455 .gate_shift = gs, \
456 .gate_flags = gf, \
457 }
458
459#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
460 df, dt, go, gs, gf) \
461 { \
462 .id = _id, \
463 .branch_type = branch_composite, \
464 .name = cname, \
465 .parent_names = (const char *[]){ pname }, \
466 .num_parents = 1, \
467 .flags = f, \
468 .muxdiv_offset = mo, \
469 .div_shift = ds, \
470 .div_width = dw, \
471 .div_flags = df, \
472 .div_table = dt, \
473 .gate_offset = go, \
474 .gate_shift = gs, \
475 .gate_flags = gf, \
476 }
477
478#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \
479 go, gs, gf) \
480 { \
481 .id = _id, \
482 .branch_type = branch_composite, \
483 .name = cname, \
484 .parent_names = pnames, \
485 .num_parents = ARRAY_SIZE(pnames), \
486 .flags = f, \
487 .muxdiv_offset = mo, \
488 .mux_shift = ms, \
489 .mux_width = mw, \
490 .mux_flags = mf, \
491 .gate_offset = go, \
492 .gate_shift = gs, \
493 .gate_flags = gf, \
494 }
495
496#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
497 ds, dw, df) \
498 { \
499 .id = _id, \
500 .branch_type = branch_composite, \
501 .name = cname, \
502 .parent_names = pnames, \
503 .num_parents = ARRAY_SIZE(pnames), \
504 .flags = f, \
505 .muxdiv_offset = mo, \
506 .mux_shift = ms, \
507 .mux_width = mw, \
508 .mux_flags = mf, \
509 .div_shift = ds, \
510 .div_width = dw, \
511 .div_flags = df, \
512 .gate_offset = -1, \
513 }
514
Heiko Stuebner6f085072015-06-18 16:18:31 +0200515#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \
516 mw, mf, ds, dw, df, dt) \
517 { \
518 .id = _id, \
519 .branch_type = branch_composite, \
520 .name = cname, \
521 .parent_names = pnames, \
522 .num_parents = ARRAY_SIZE(pnames), \
523 .flags = f, \
524 .muxdiv_offset = mo, \
525 .mux_shift = ms, \
526 .mux_width = mw, \
527 .mux_flags = mf, \
528 .div_shift = ds, \
529 .div_width = dw, \
530 .div_flags = df, \
531 .div_table = dt, \
532 .gate_offset = -1, \
533 }
534
Heiko Stübnera245fec2014-07-03 01:58:39 +0200535#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
536 { \
537 .id = _id, \
538 .branch_type = branch_fraction_divider, \
539 .name = cname, \
540 .parent_names = (const char *[]){ pname }, \
541 .num_parents = 1, \
542 .flags = f, \
543 .muxdiv_offset = mo, \
544 .div_shift = 16, \
545 .div_width = 16, \
546 .div_flags = df, \
547 .gate_offset = go, \
548 .gate_shift = gs, \
549 .gate_flags = gf, \
550 }
551
Heiko Stuebner8ca1ca82015-12-22 22:27:59 +0100552#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
553 { \
554 .id = _id, \
555 .branch_type = branch_fraction_divider, \
556 .name = cname, \
557 .parent_names = (const char *[]){ pname }, \
558 .num_parents = 1, \
559 .flags = f, \
560 .muxdiv_offset = mo, \
561 .div_shift = 16, \
562 .div_width = 16, \
563 .div_flags = df, \
564 .gate_offset = go, \
565 .gate_shift = gs, \
566 .gate_flags = gf, \
Heiko Stübner5b738402015-12-26 14:07:15 +0100567 .child = ch, \
Heiko Stuebner8ca1ca82015-12-22 22:27:59 +0100568 }
569
Xing Zheng9387bfd2016-03-09 10:43:31 +0800570#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \
571 { \
572 .id = _id, \
573 .branch_type = branch_fraction_divider, \
574 .name = cname, \
575 .parent_names = (const char *[]){ pname }, \
576 .num_parents = 1, \
577 .flags = f, \
578 .muxdiv_offset = mo, \
579 .div_shift = 16, \
580 .div_width = 16, \
581 .div_flags = df, \
582 .gate_offset = -1, \
583 .child = ch, \
584 }
585
Lin Huanga4f182b2016-08-22 11:36:17 +0800586#define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, \
587 ds, dw, df) \
588 { \
589 .id = _id, \
590 .branch_type = branch_ddrclk, \
591 .name = cname, \
592 .parent_names = pnames, \
593 .num_parents = ARRAY_SIZE(pnames), \
594 .flags = f, \
595 .muxdiv_offset = mo, \
596 .mux_shift = ms, \
597 .mux_width = mw, \
598 .div_shift = ds, \
599 .div_width = dw, \
600 .div_flags = df, \
601 .gate_offset = -1, \
602 }
603
Heiko Stübnera245fec2014-07-03 01:58:39 +0200604#define MUX(_id, cname, pnames, f, o, s, w, mf) \
605 { \
606 .id = _id, \
607 .branch_type = branch_mux, \
608 .name = cname, \
609 .parent_names = pnames, \
610 .num_parents = ARRAY_SIZE(pnames), \
611 .flags = f, \
612 .muxdiv_offset = o, \
613 .mux_shift = s, \
614 .mux_width = w, \
615 .mux_flags = mf, \
616 .gate_offset = -1, \
617 }
618
Heiko Stuebnercb1d9f62016-12-27 00:00:38 +0100619#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \
620 { \
621 .id = _id, \
622 .branch_type = branch_muxgrf, \
623 .name = cname, \
624 .parent_names = pnames, \
625 .num_parents = ARRAY_SIZE(pnames), \
626 .flags = f, \
627 .muxdiv_offset = o, \
628 .mux_shift = s, \
629 .mux_width = w, \
630 .mux_flags = mf, \
631 .gate_offset = -1, \
632 }
633
Heiko Stübnera245fec2014-07-03 01:58:39 +0200634#define DIV(_id, cname, pname, f, o, s, w, df) \
635 { \
636 .id = _id, \
637 .branch_type = branch_divider, \
638 .name = cname, \
639 .parent_names = (const char *[]){ pname }, \
640 .num_parents = 1, \
641 .flags = f, \
642 .muxdiv_offset = o, \
643 .div_shift = s, \
644 .div_width = w, \
645 .div_flags = df, \
646 .gate_offset = -1, \
647 }
648
649#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
650 { \
651 .id = _id, \
652 .branch_type = branch_divider, \
653 .name = cname, \
654 .parent_names = (const char *[]){ pname }, \
655 .num_parents = 1, \
656 .flags = f, \
657 .muxdiv_offset = o, \
658 .div_shift = s, \
659 .div_width = w, \
660 .div_flags = df, \
661 .div_table = dt, \
662 }
663
664#define GATE(_id, cname, pname, f, o, b, gf) \
665 { \
666 .id = _id, \
667 .branch_type = branch_gate, \
668 .name = cname, \
669 .parent_names = (const char *[]){ pname }, \
670 .num_parents = 1, \
671 .flags = f, \
672 .gate_offset = o, \
673 .gate_shift = b, \
674 .gate_flags = gf, \
675 }
676
Alexandru M Stan89bf26c2014-11-26 17:30:27 -0800677#define MMC(_id, cname, pname, offset, shift) \
678 { \
679 .id = _id, \
680 .branch_type = branch_mmc, \
681 .name = cname, \
682 .parent_names = (const char *[]){ pname }, \
683 .num_parents = 1, \
684 .muxdiv_offset = offset, \
685 .div_shift = shift, \
686 }
Heiko Stübnera245fec2014-07-03 01:58:39 +0200687
Heiko Stuebner8a76f442015-07-05 11:00:14 +0200688#define INVERTER(_id, cname, pname, io, is, if) \
689 { \
690 .id = _id, \
691 .branch_type = branch_inverter, \
692 .name = cname, \
693 .parent_names = (const char *[]){ pname }, \
694 .num_parents = 1, \
695 .muxdiv_offset = io, \
696 .div_shift = is, \
697 .div_flags = if, \
698 }
699
Heiko Stuebner29a30c22015-06-20 13:08:57 +0200700#define FACTOR(_id, cname, pname, f, fm, fd) \
701 { \
702 .id = _id, \
703 .branch_type = branch_factor, \
704 .name = cname, \
705 .parent_names = (const char *[]){ pname }, \
706 .num_parents = 1, \
707 .flags = f, \
708 .div_shift = fm, \
709 .div_width = fd, \
710 }
711
712#define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \
713 { \
714 .id = _id, \
715 .branch_type = branch_factor, \
716 .name = cname, \
717 .parent_names = (const char *[]){ pname }, \
718 .num_parents = 1, \
719 .flags = f, \
720 .div_shift = fm, \
721 .div_width = fd, \
722 .gate_offset = go, \
723 .gate_shift = gb, \
724 .gate_flags = gf, \
725 }
726
Elaine Zhang956060a2018-06-15 10:16:50 +0800727#define COMPOSITE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
728 df, go, gs, gf) \
729 { \
730 .id = _id, \
731 .branch_type = branch_half_divider, \
732 .name = cname, \
733 .parent_names = pnames, \
734 .num_parents = ARRAY_SIZE(pnames), \
735 .flags = f, \
736 .muxdiv_offset = mo, \
737 .mux_shift = ms, \
738 .mux_width = mw, \
739 .mux_flags = mf, \
740 .div_shift = ds, \
741 .div_width = dw, \
742 .div_flags = df, \
743 .gate_offset = go, \
744 .gate_shift = gs, \
745 .gate_flags = gf, \
746 }
747
748#define COMPOSITE_NOGATE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, \
749 ds, dw, df) \
750 { \
751 .id = _id, \
752 .branch_type = branch_half_divider, \
753 .name = cname, \
754 .parent_names = pnames, \
755 .num_parents = ARRAY_SIZE(pnames), \
756 .flags = f, \
757 .muxdiv_offset = mo, \
758 .mux_shift = ms, \
759 .mux_width = mw, \
760 .mux_flags = mf, \
761 .div_shift = ds, \
762 .div_width = dw, \
763 .div_flags = df, \
764 .gate_offset = -1, \
765 }
766
767#define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, \
768 go, gs, gf) \
769 { \
770 .id = _id, \
771 .branch_type = branch_half_divider, \
772 .name = cname, \
773 .parent_names = (const char *[]){ pname }, \
774 .num_parents = 1, \
775 .flags = f, \
776 .muxdiv_offset = mo, \
777 .div_shift = ds, \
778 .div_width = dw, \
779 .div_flags = df, \
780 .gate_offset = go, \
781 .gate_shift = gs, \
782 .gate_flags = gf, \
783 }
784
785#define DIV_HALF(_id, cname, pname, f, o, s, w, df) \
786 { \
787 .id = _id, \
788 .branch_type = branch_half_divider, \
789 .name = cname, \
790 .parent_names = (const char *[]){ pname }, \
791 .num_parents = 1, \
792 .flags = f, \
793 .muxdiv_offset = o, \
794 .div_shift = s, \
795 .div_width = w, \
796 .div_flags = df, \
797 .gate_offset = -1, \
798 }
799
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800800struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
801 void __iomem *base, unsigned long nr_clks);
802void rockchip_clk_of_add_provider(struct device_node *np,
803 struct rockchip_clk_provider *ctx);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800804void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
805 struct clk *clk, unsigned int id);
806void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
807 struct rockchip_clk_branch *list,
Heiko Stübnera245fec2014-07-03 01:58:39 +0200808 unsigned int nr_clk);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800809void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
810 struct rockchip_pll_clock *pll_list,
Heiko Stübner90c59022014-07-03 01:59:10 +0200811 unsigned int nr_pll, int grf_lock_offset);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800812void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
813 unsigned int lookup_id, const char *name,
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200814 const char *const *parent_names, u8 num_parents,
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200815 const struct rockchip_cpuclk_reg_data *reg_data,
816 const struct rockchip_cpuclk_rate_table *rates,
817 int nrates);
Uwe Kleine-König692d8322015-02-18 10:59:45 +0100818void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800819void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
820 unsigned int reg, void (*cb)(void));
Heiko Stübnera245fec2014-07-03 01:58:39 +0200821
Heiko Stübner85fa0c72014-07-03 01:59:39 +0200822#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
823
Elaine Zhang956060a2018-06-15 10:16:50 +0800824struct clk *rockchip_clk_register_halfdiv(const char *name,
825 const char *const *parent_names,
826 u8 num_parents, void __iomem *base,
827 int muxdiv_offset, u8 mux_shift,
828 u8 mux_width, u8 mux_flags,
829 u8 div_shift, u8 div_width,
830 u8 div_flags, int gate_offset,
831 u8 gate_shift, u8 gate_flags,
832 unsigned long flags,
833 spinlock_t *lock);
834
Heiko Stübner85fa0c72014-07-03 01:59:39 +0200835#ifdef CONFIG_RESET_CONTROLLER
836void rockchip_register_softrst(struct device_node *np,
837 unsigned int num_regs,
838 void __iomem *base, u8 flags);
839#else
840static inline void rockchip_register_softrst(struct device_node *np,
841 unsigned int num_regs,
842 void __iomem *base, u8 flags)
843{
844}
845#endif
846
Heiko Stübnera245fec2014-07-03 01:58:39 +0200847#endif