blob: 1b527075543108256c4bca2d0aa960c482ae12f5 [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 Zheng9c4d6e552015-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 Zheng9c4d6e552015-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 Zheng9c4d6e552015-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 Zheng9c4d6e552015-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;
Finley Xiao1f55660ff2019-04-03 17:42:26 +0800410 int div_offset;
Heiko Stübnera245fec2014-07-03 01:58:39 +0200411 u8 div_shift;
412 u8 div_width;
413 u8 div_flags;
414 struct clk_div_table *div_table;
415 int gate_offset;
416 u8 gate_shift;
417 u8 gate_flags;
Heiko Stuebner8ca1ca82015-12-22 22:27:59 +0100418 struct rockchip_clk_branch *child;
Heiko Stübnera245fec2014-07-03 01:58:39 +0200419};
420
421#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
422 df, go, gs, gf) \
423 { \
424 .id = _id, \
425 .branch_type = branch_composite, \
426 .name = cname, \
427 .parent_names = pnames, \
428 .num_parents = ARRAY_SIZE(pnames), \
429 .flags = f, \
430 .muxdiv_offset = mo, \
431 .mux_shift = ms, \
432 .mux_width = mw, \
433 .mux_flags = mf, \
434 .div_shift = ds, \
435 .div_width = dw, \
436 .div_flags = df, \
437 .gate_offset = go, \
438 .gate_shift = gs, \
439 .gate_flags = gf, \
440 }
441
Finley Xiao1f55660ff2019-04-03 17:42:26 +0800442#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw, \
443 mf, do, ds, dw, df, go, gs, gf) \
444 { \
445 .id = _id, \
446 .branch_type = branch_composite, \
447 .name = cname, \
448 .parent_names = pnames, \
449 .num_parents = ARRAY_SIZE(pnames), \
450 .flags = f, \
451 .muxdiv_offset = mo, \
452 .mux_shift = ms, \
453 .mux_width = mw, \
454 .mux_flags = mf, \
455 .div_offset = do, \
456 .div_shift = ds, \
457 .div_width = dw, \
458 .div_flags = df, \
459 .gate_offset = go, \
460 .gate_shift = gs, \
461 .gate_flags = gf, \
462 }
463
Heiko Stübnera245fec2014-07-03 01:58:39 +0200464#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
465 go, gs, gf) \
466 { \
467 .id = _id, \
468 .branch_type = branch_composite, \
469 .name = cname, \
470 .parent_names = (const char *[]){ pname }, \
471 .num_parents = 1, \
472 .flags = f, \
473 .muxdiv_offset = mo, \
474 .div_shift = ds, \
475 .div_width = dw, \
476 .div_flags = df, \
477 .gate_offset = go, \
478 .gate_shift = gs, \
479 .gate_flags = gf, \
480 }
481
482#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
483 df, dt, go, gs, gf) \
484 { \
485 .id = _id, \
486 .branch_type = branch_composite, \
487 .name = cname, \
488 .parent_names = (const char *[]){ pname }, \
489 .num_parents = 1, \
490 .flags = f, \
491 .muxdiv_offset = mo, \
492 .div_shift = ds, \
493 .div_width = dw, \
494 .div_flags = df, \
495 .div_table = dt, \
496 .gate_offset = go, \
497 .gate_shift = gs, \
498 .gate_flags = gf, \
499 }
500
501#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \
502 go, gs, gf) \
503 { \
504 .id = _id, \
505 .branch_type = branch_composite, \
506 .name = cname, \
507 .parent_names = pnames, \
508 .num_parents = ARRAY_SIZE(pnames), \
509 .flags = f, \
510 .muxdiv_offset = mo, \
511 .mux_shift = ms, \
512 .mux_width = mw, \
513 .mux_flags = mf, \
514 .gate_offset = go, \
515 .gate_shift = gs, \
516 .gate_flags = gf, \
517 }
518
519#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
520 ds, dw, df) \
521 { \
522 .id = _id, \
523 .branch_type = branch_composite, \
524 .name = cname, \
525 .parent_names = pnames, \
526 .num_parents = ARRAY_SIZE(pnames), \
527 .flags = f, \
528 .muxdiv_offset = mo, \
529 .mux_shift = ms, \
530 .mux_width = mw, \
531 .mux_flags = mf, \
532 .div_shift = ds, \
533 .div_width = dw, \
534 .div_flags = df, \
535 .gate_offset = -1, \
536 }
537
Heiko Stuebner6f085072015-06-18 16:18:31 +0200538#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \
539 mw, mf, ds, dw, df, dt) \
540 { \
541 .id = _id, \
542 .branch_type = branch_composite, \
543 .name = cname, \
544 .parent_names = pnames, \
545 .num_parents = ARRAY_SIZE(pnames), \
546 .flags = f, \
547 .muxdiv_offset = mo, \
548 .mux_shift = ms, \
549 .mux_width = mw, \
550 .mux_flags = mf, \
551 .div_shift = ds, \
552 .div_width = dw, \
553 .div_flags = df, \
554 .div_table = dt, \
555 .gate_offset = -1, \
556 }
557
Heiko Stübnera245fec2014-07-03 01:58:39 +0200558#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
559 { \
560 .id = _id, \
561 .branch_type = branch_fraction_divider, \
562 .name = cname, \
563 .parent_names = (const char *[]){ pname }, \
564 .num_parents = 1, \
565 .flags = f, \
566 .muxdiv_offset = mo, \
567 .div_shift = 16, \
568 .div_width = 16, \
569 .div_flags = df, \
570 .gate_offset = go, \
571 .gate_shift = gs, \
572 .gate_flags = gf, \
573 }
574
Heiko Stuebner8ca1ca82015-12-22 22:27:59 +0100575#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
576 { \
577 .id = _id, \
578 .branch_type = branch_fraction_divider, \
579 .name = cname, \
580 .parent_names = (const char *[]){ pname }, \
581 .num_parents = 1, \
582 .flags = f, \
583 .muxdiv_offset = mo, \
584 .div_shift = 16, \
585 .div_width = 16, \
586 .div_flags = df, \
587 .gate_offset = go, \
588 .gate_shift = gs, \
589 .gate_flags = gf, \
Heiko Stübner5b738402015-12-26 14:07:15 +0100590 .child = ch, \
Heiko Stuebner8ca1ca82015-12-22 22:27:59 +0100591 }
592
Xing Zheng9387bfd2016-03-09 10:43:31 +0800593#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \
594 { \
595 .id = _id, \
596 .branch_type = branch_fraction_divider, \
597 .name = cname, \
598 .parent_names = (const char *[]){ pname }, \
599 .num_parents = 1, \
600 .flags = f, \
601 .muxdiv_offset = mo, \
602 .div_shift = 16, \
603 .div_width = 16, \
604 .div_flags = df, \
605 .gate_offset = -1, \
606 .child = ch, \
607 }
608
Lin Huanga4f182b2016-08-22 11:36:17 +0800609#define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, \
610 ds, dw, df) \
611 { \
612 .id = _id, \
613 .branch_type = branch_ddrclk, \
614 .name = cname, \
615 .parent_names = pnames, \
616 .num_parents = ARRAY_SIZE(pnames), \
617 .flags = f, \
618 .muxdiv_offset = mo, \
619 .mux_shift = ms, \
620 .mux_width = mw, \
621 .div_shift = ds, \
622 .div_width = dw, \
623 .div_flags = df, \
624 .gate_offset = -1, \
625 }
626
Heiko Stübnera245fec2014-07-03 01:58:39 +0200627#define MUX(_id, cname, pnames, f, o, s, w, mf) \
628 { \
629 .id = _id, \
630 .branch_type = branch_mux, \
631 .name = cname, \
632 .parent_names = pnames, \
633 .num_parents = ARRAY_SIZE(pnames), \
634 .flags = f, \
635 .muxdiv_offset = o, \
636 .mux_shift = s, \
637 .mux_width = w, \
638 .mux_flags = mf, \
639 .gate_offset = -1, \
640 }
641
Heiko Stuebnercb1d9f62016-12-27 00:00:38 +0100642#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \
643 { \
644 .id = _id, \
645 .branch_type = branch_muxgrf, \
646 .name = cname, \
647 .parent_names = pnames, \
648 .num_parents = ARRAY_SIZE(pnames), \
649 .flags = f, \
650 .muxdiv_offset = o, \
651 .mux_shift = s, \
652 .mux_width = w, \
653 .mux_flags = mf, \
654 .gate_offset = -1, \
655 }
656
Heiko Stübnera245fec2014-07-03 01:58:39 +0200657#define DIV(_id, cname, pname, f, o, s, w, df) \
658 { \
659 .id = _id, \
660 .branch_type = branch_divider, \
661 .name = cname, \
662 .parent_names = (const char *[]){ pname }, \
663 .num_parents = 1, \
664 .flags = f, \
665 .muxdiv_offset = o, \
666 .div_shift = s, \
667 .div_width = w, \
668 .div_flags = df, \
669 .gate_offset = -1, \
670 }
671
672#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
673 { \
674 .id = _id, \
675 .branch_type = branch_divider, \
676 .name = cname, \
677 .parent_names = (const char *[]){ pname }, \
678 .num_parents = 1, \
679 .flags = f, \
680 .muxdiv_offset = o, \
681 .div_shift = s, \
682 .div_width = w, \
683 .div_flags = df, \
684 .div_table = dt, \
685 }
686
687#define GATE(_id, cname, pname, f, o, b, gf) \
688 { \
689 .id = _id, \
690 .branch_type = branch_gate, \
691 .name = cname, \
692 .parent_names = (const char *[]){ pname }, \
693 .num_parents = 1, \
694 .flags = f, \
695 .gate_offset = o, \
696 .gate_shift = b, \
697 .gate_flags = gf, \
698 }
699
Alexandru M Stan89bf26c2014-11-26 17:30:27 -0800700#define MMC(_id, cname, pname, offset, shift) \
701 { \
702 .id = _id, \
703 .branch_type = branch_mmc, \
704 .name = cname, \
705 .parent_names = (const char *[]){ pname }, \
706 .num_parents = 1, \
707 .muxdiv_offset = offset, \
708 .div_shift = shift, \
709 }
Heiko Stübnera245fec2014-07-03 01:58:39 +0200710
Heiko Stuebner8a76f442015-07-05 11:00:14 +0200711#define INVERTER(_id, cname, pname, io, is, if) \
712 { \
713 .id = _id, \
714 .branch_type = branch_inverter, \
715 .name = cname, \
716 .parent_names = (const char *[]){ pname }, \
717 .num_parents = 1, \
718 .muxdiv_offset = io, \
719 .div_shift = is, \
720 .div_flags = if, \
721 }
722
Heiko Stuebner29a30c22015-06-20 13:08:57 +0200723#define FACTOR(_id, cname, pname, f, fm, fd) \
724 { \
725 .id = _id, \
726 .branch_type = branch_factor, \
727 .name = cname, \
728 .parent_names = (const char *[]){ pname }, \
729 .num_parents = 1, \
730 .flags = f, \
731 .div_shift = fm, \
732 .div_width = fd, \
733 }
734
735#define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \
736 { \
737 .id = _id, \
738 .branch_type = branch_factor, \
739 .name = cname, \
740 .parent_names = (const char *[]){ pname }, \
741 .num_parents = 1, \
742 .flags = f, \
743 .div_shift = fm, \
744 .div_width = fd, \
745 .gate_offset = go, \
746 .gate_shift = gb, \
747 .gate_flags = gf, \
748 }
749
Elaine Zhang956060a2018-06-15 10:16:50 +0800750#define COMPOSITE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
751 df, go, gs, gf) \
752 { \
753 .id = _id, \
754 .branch_type = branch_half_divider, \
755 .name = cname, \
756 .parent_names = pnames, \
757 .num_parents = ARRAY_SIZE(pnames), \
758 .flags = f, \
759 .muxdiv_offset = mo, \
760 .mux_shift = ms, \
761 .mux_width = mw, \
762 .mux_flags = mf, \
763 .div_shift = ds, \
764 .div_width = dw, \
765 .div_flags = df, \
766 .gate_offset = go, \
767 .gate_shift = gs, \
768 .gate_flags = gf, \
769 }
770
771#define COMPOSITE_NOGATE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, \
772 ds, dw, df) \
773 { \
774 .id = _id, \
775 .branch_type = branch_half_divider, \
776 .name = cname, \
777 .parent_names = pnames, \
778 .num_parents = ARRAY_SIZE(pnames), \
779 .flags = f, \
780 .muxdiv_offset = mo, \
781 .mux_shift = ms, \
782 .mux_width = mw, \
783 .mux_flags = mf, \
784 .div_shift = ds, \
785 .div_width = dw, \
786 .div_flags = df, \
787 .gate_offset = -1, \
788 }
789
790#define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, \
791 go, gs, gf) \
792 { \
793 .id = _id, \
794 .branch_type = branch_half_divider, \
795 .name = cname, \
796 .parent_names = (const char *[]){ pname }, \
797 .num_parents = 1, \
798 .flags = f, \
799 .muxdiv_offset = mo, \
800 .div_shift = ds, \
801 .div_width = dw, \
802 .div_flags = df, \
803 .gate_offset = go, \
804 .gate_shift = gs, \
805 .gate_flags = gf, \
806 }
807
808#define DIV_HALF(_id, cname, pname, f, o, s, w, df) \
809 { \
810 .id = _id, \
811 .branch_type = branch_half_divider, \
812 .name = cname, \
813 .parent_names = (const char *[]){ pname }, \
814 .num_parents = 1, \
815 .flags = f, \
816 .muxdiv_offset = o, \
817 .div_shift = s, \
818 .div_width = w, \
819 .div_flags = df, \
820 .gate_offset = -1, \
821 }
822
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800823struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
824 void __iomem *base, unsigned long nr_clks);
825void rockchip_clk_of_add_provider(struct device_node *np,
826 struct rockchip_clk_provider *ctx);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800827void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
828 struct clk *clk, unsigned int id);
829void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
830 struct rockchip_clk_branch *list,
Heiko Stübnera245fec2014-07-03 01:58:39 +0200831 unsigned int nr_clk);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800832void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
833 struct rockchip_pll_clock *pll_list,
Heiko Stübner90c59022014-07-03 01:59:10 +0200834 unsigned int nr_pll, int grf_lock_offset);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800835void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
836 unsigned int lookup_id, const char *name,
Uwe Kleine-König4a1caed2015-05-28 10:45:51 +0200837 const char *const *parent_names, u8 num_parents,
Heiko Stuebnerf6fba5f2014-09-04 22:10:43 +0200838 const struct rockchip_cpuclk_reg_data *reg_data,
839 const struct rockchip_cpuclk_rate_table *rates,
840 int nrates);
Uwe Kleine-König692d8322015-02-18 10:59:45 +0100841void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
Xing Zhengef1d9fe2016-03-09 10:37:04 +0800842void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
843 unsigned int reg, void (*cb)(void));
Heiko Stübnera245fec2014-07-03 01:58:39 +0200844
Heiko Stübner85fa0c72014-07-03 01:59:39 +0200845#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
846
Elaine Zhang956060a2018-06-15 10:16:50 +0800847struct clk *rockchip_clk_register_halfdiv(const char *name,
848 const char *const *parent_names,
849 u8 num_parents, void __iomem *base,
850 int muxdiv_offset, u8 mux_shift,
851 u8 mux_width, u8 mux_flags,
852 u8 div_shift, u8 div_width,
853 u8 div_flags, int gate_offset,
854 u8 gate_shift, u8 gate_flags,
855 unsigned long flags,
856 spinlock_t *lock);
857
Heiko Stübner85fa0c72014-07-03 01:59:39 +0200858#ifdef CONFIG_RESET_CONTROLLER
859void rockchip_register_softrst(struct device_node *np,
860 unsigned int num_regs,
861 void __iomem *base, u8 flags);
862#else
863static inline void rockchip_register_softrst(struct device_node *np,
864 unsigned int num_regs,
865 void __iomem *base, u8 flags)
866{
867}
868#endif
869
Heiko Stübnera245fec2014-07-03 01:58:39 +0200870#endif