xref: /linux/drivers/clk/sifive/sifive-prci.h (revision b77e0ce62d63a761ffb7f7245a215a49f5921c2f)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2018-2019 SiFive, Inc.
4  * Wesley Terpstra
5  * Paul Walmsley
6  * Zong Li
7  */
8 
9 #ifndef __SIFIVE_CLK_SIFIVE_PRCI_H
10 #define __SIFIVE_CLK_SIFIVE_PRCI_H
11 
12 #include <linux/clk/analogbits-wrpll-cln28hpc.h>
13 #include <linux/clk-provider.h>
14 #include <linux/platform_device.h>
15 
16 /*
17  * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
18  *     hfclk and rtcclk
19  */
20 #define EXPECTED_CLK_PARENT_COUNT 2
21 
22 /*
23  * Register offsets and bitmasks
24  */
25 
26 /* COREPLLCFG0 */
27 #define PRCI_COREPLLCFG0_OFFSET		0x4
28 #define PRCI_COREPLLCFG0_DIVR_SHIFT	0
29 #define PRCI_COREPLLCFG0_DIVR_MASK	(0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
30 #define PRCI_COREPLLCFG0_DIVF_SHIFT	6
31 #define PRCI_COREPLLCFG0_DIVF_MASK	(0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
32 #define PRCI_COREPLLCFG0_DIVQ_SHIFT	15
33 #define PRCI_COREPLLCFG0_DIVQ_MASK	(0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
34 #define PRCI_COREPLLCFG0_RANGE_SHIFT	18
35 #define PRCI_COREPLLCFG0_RANGE_MASK	(0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
36 #define PRCI_COREPLLCFG0_BYPASS_SHIFT	24
37 #define PRCI_COREPLLCFG0_BYPASS_MASK	(0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
38 #define PRCI_COREPLLCFG0_FSE_SHIFT	25
39 #define PRCI_COREPLLCFG0_FSE_MASK	(0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
40 #define PRCI_COREPLLCFG0_LOCK_SHIFT	31
41 #define PRCI_COREPLLCFG0_LOCK_MASK	(0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
42 
43 /* COREPLLCFG1 */
44 #define PRCI_COREPLLCFG1_OFFSET		0x8
45 #define PRCI_COREPLLCFG1_CKE_SHIFT	31
46 #define PRCI_COREPLLCFG1_CKE_MASK	(0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
47 
48 /* DDRPLLCFG0 */
49 #define PRCI_DDRPLLCFG0_OFFSET		0xc
50 #define PRCI_DDRPLLCFG0_DIVR_SHIFT	0
51 #define PRCI_DDRPLLCFG0_DIVR_MASK	(0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
52 #define PRCI_DDRPLLCFG0_DIVF_SHIFT	6
53 #define PRCI_DDRPLLCFG0_DIVF_MASK	(0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
54 #define PRCI_DDRPLLCFG0_DIVQ_SHIFT	15
55 #define PRCI_DDRPLLCFG0_DIVQ_MASK	(0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
56 #define PRCI_DDRPLLCFG0_RANGE_SHIFT	18
57 #define PRCI_DDRPLLCFG0_RANGE_MASK	(0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
58 #define PRCI_DDRPLLCFG0_BYPASS_SHIFT	24
59 #define PRCI_DDRPLLCFG0_BYPASS_MASK	(0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
60 #define PRCI_DDRPLLCFG0_FSE_SHIFT	25
61 #define PRCI_DDRPLLCFG0_FSE_MASK	(0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
62 #define PRCI_DDRPLLCFG0_LOCK_SHIFT	31
63 #define PRCI_DDRPLLCFG0_LOCK_MASK	(0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
64 
65 /* DDRPLLCFG1 */
66 #define PRCI_DDRPLLCFG1_OFFSET		0x10
67 #define PRCI_DDRPLLCFG1_CKE_SHIFT	31
68 #define PRCI_DDRPLLCFG1_CKE_MASK	(0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
69 
70 /* GEMGXLPLLCFG0 */
71 #define PRCI_GEMGXLPLLCFG0_OFFSET	0x1c
72 #define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT	0
73 #define PRCI_GEMGXLPLLCFG0_DIVR_MASK	(0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
74 #define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT	6
75 #define PRCI_GEMGXLPLLCFG0_DIVF_MASK	(0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
76 #define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT	15
77 #define PRCI_GEMGXLPLLCFG0_DIVQ_MASK	(0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
78 #define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT	18
79 #define PRCI_GEMGXLPLLCFG0_RANGE_MASK	(0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
80 #define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT	24
81 #define PRCI_GEMGXLPLLCFG0_BYPASS_MASK	(0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
82 #define PRCI_GEMGXLPLLCFG0_FSE_SHIFT	25
83 #define PRCI_GEMGXLPLLCFG0_FSE_MASK	(0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
84 #define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT	31
85 #define PRCI_GEMGXLPLLCFG0_LOCK_MASK	(0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
86 
87 /* GEMGXLPLLCFG1 */
88 #define PRCI_GEMGXLPLLCFG1_OFFSET	0x20
89 #define PRCI_GEMGXLPLLCFG1_CKE_SHIFT	31
90 #define PRCI_GEMGXLPLLCFG1_CKE_MASK	(0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
91 
92 /* CORECLKSEL */
93 #define PRCI_CORECLKSEL_OFFSET			0x24
94 #define PRCI_CORECLKSEL_CORECLKSEL_SHIFT	0
95 #define PRCI_CORECLKSEL_CORECLKSEL_MASK					\
96 		(0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
97 
98 /* DEVICESRESETREG */
99 #define PRCI_DEVICESRESETREG_OFFSET				0x28
100 #define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT		0
101 #define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK			\
102 		(0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
103 #define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT		1
104 #define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK				\
105 		(0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
106 #define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT		2
107 #define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK				\
108 		(0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
109 #define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT		3
110 #define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK				\
111 		(0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
112 #define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT			5
113 #define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK				\
114 		(0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
115 #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT		6
116 #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK			\
117 		(0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT)
118 
119 /* CLKMUXSTATUSREG */
120 #define PRCI_CLKMUXSTATUSREG_OFFSET				0x2c
121 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT		1
122 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK			\
123 		(0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
124 
125 /* CLTXPLLCFG0 */
126 #define PRCI_CLTXPLLCFG0_OFFSET		0x30
127 #define PRCI_CLTXPLLCFG0_DIVR_SHIFT	0
128 #define PRCI_CLTXPLLCFG0_DIVR_MASK	(0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)
129 #define PRCI_CLTXPLLCFG0_DIVF_SHIFT	6
130 #define PRCI_CLTXPLLCFG0_DIVF_MASK	(0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)
131 #define PRCI_CLTXPLLCFG0_DIVQ_SHIFT	15
132 #define PRCI_CLTXPLLCFG0_DIVQ_MASK	(0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)
133 #define PRCI_CLTXPLLCFG0_RANGE_SHIFT	18
134 #define PRCI_CLTXPLLCFG0_RANGE_MASK	(0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)
135 #define PRCI_CLTXPLLCFG0_BYPASS_SHIFT	24
136 #define PRCI_CLTXPLLCFG0_BYPASS_MASK	(0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)
137 #define PRCI_CLTXPLLCFG0_FSE_SHIFT	25
138 #define PRCI_CLTXPLLCFG0_FSE_MASK	(0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)
139 #define PRCI_CLTXPLLCFG0_LOCK_SHIFT	31
140 #define PRCI_CLTXPLLCFG0_LOCK_MASK	(0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)
141 
142 /* CLTXPLLCFG1 */
143 #define PRCI_CLTXPLLCFG1_OFFSET		0x34
144 #define PRCI_CLTXPLLCFG1_CKE_SHIFT	31
145 #define PRCI_CLTXPLLCFG1_CKE_MASK	(0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)
146 
147 /* DVFSCOREPLLCFG0 */
148 #define PRCI_DVFSCOREPLLCFG0_OFFSET	0x38
149 
150 /* DVFSCOREPLLCFG1 */
151 #define PRCI_DVFSCOREPLLCFG1_OFFSET	0x3c
152 #define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT	31
153 #define PRCI_DVFSCOREPLLCFG1_CKE_MASK	(0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)
154 
155 /* COREPLLSEL */
156 #define PRCI_COREPLLSEL_OFFSET			0x40
157 #define PRCI_COREPLLSEL_COREPLLSEL_SHIFT	0
158 #define PRCI_COREPLLSEL_COREPLLSEL_MASK					\
159 		(0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)
160 
161 /* HFPCLKPLLCFG0 */
162 #define PRCI_HFPCLKPLLCFG0_OFFSET		0x50
163 #define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT		0
164 #define PRCI_HFPCLKPLL_CFG0_DIVR_MASK					\
165 		(0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)
166 #define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT		6
167 #define PRCI_HFPCLKPLL_CFG0_DIVF_MASK					\
168 		(0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)
169 #define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT		15
170 #define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK					\
171 		(0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)
172 #define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT		18
173 #define PRCI_HFPCLKPLL_CFG0_RANGE_MASK					\
174 		(0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)
175 #define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT	24
176 #define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK					\
177 		(0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)
178 #define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT		25
179 #define PRCI_HFPCLKPLL_CFG0_FSE_MASK					\
180 		(0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)
181 #define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT		31
182 #define PRCI_HFPCLKPLL_CFG0_LOCK_MASK					\
183 		(0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)
184 
185 /* HFPCLKPLLCFG1 */
186 #define PRCI_HFPCLKPLLCFG1_OFFSET		0x54
187 #define PRCI_HFPCLKPLLCFG1_CKE_SHIFT		31
188 #define PRCI_HFPCLKPLLCFG1_CKE_MASK					\
189 		(0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)
190 
191 /* HFPCLKPLLSEL */
192 #define PRCI_HFPCLKPLLSEL_OFFSET		0x58
193 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT	0
194 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK				\
195 		(0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)
196 
197 /* HFPCLKPLLDIV */
198 #define PRCI_HFPCLKPLLDIV_OFFSET		0x5c
199 
200 /* PRCIPLL */
201 #define PRCI_PRCIPLL_OFFSET			0xe0
202 
203 /* PROCMONCFG */
204 #define PRCI_PROCMONCFG_OFFSET			0xf0
205 
206 /*
207  * Private structures
208  */
209 
210 /**
211  * struct __prci_data - per-device-instance data
212  * @va: base virtual address of the PRCI IP block
213  * @hw_clks: encapsulates struct clk_hw records
214  *
215  * PRCI per-device instance data
216  */
217 struct __prci_data {
218 	void __iomem *va;
219 	struct clk_hw_onecell_data hw_clks;
220 };
221 
222 /**
223  * struct __prci_wrpll_data - WRPLL configuration and integration data
224  * @c: WRPLL current configuration record
225  * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
226  * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
227  * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
228  * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
229  *
230  * @enable_bypass and @disable_bypass are used for WRPLL instances
231  * that contain a separate external glitchless clock mux downstream
232  * from the PLL.  The WRPLL internal bypass mux is not glitchless.
233  */
234 struct __prci_wrpll_data {
235 	struct wrpll_cfg c;
236 	void (*enable_bypass)(struct __prci_data *pd);
237 	void (*disable_bypass)(struct __prci_data *pd);
238 	u8 cfg0_offs;
239 	u8 cfg1_offs;
240 };
241 
242 /**
243  * struct __prci_clock - describes a clock device managed by PRCI
244  * @name: user-readable clock name string - should match the manual
245  * @parent_name: parent name for this clock
246  * @ops: struct clk_ops for the Linux clock framework to use for control
247  * @hw: Linux-private clock data
248  * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
249  * @pd: PRCI-specific data associated with this clock (if not NULL)
250  *
251  * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
252  * clocks to the Linux clock infrastructure.
253  */
254 struct __prci_clock {
255 	const char *name;
256 	const char *parent_name;
257 	const struct clk_ops *ops;
258 	struct clk_hw hw;
259 	struct __prci_wrpll_data *pwd;
260 	struct __prci_data *pd;
261 };
262 
263 #define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
264 
265 /*
266  * struct prci_clk_desc - describes the information of clocks of each SoCs
267  * @clks: point to a array of __prci_clock
268  * @num_clks: the number of element of clks
269  */
270 struct prci_clk_desc {
271 	struct __prci_clock *clks;
272 	size_t num_clks;
273 };
274 
275 /* Core clock mux control */
276 void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
277 void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
278 void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);
279 void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);
280 void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);
281 void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
282 void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
283 
284 /* Linux clock framework integration */
285 long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
286 				  unsigned long *parent_rate);
287 int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,
288 			       unsigned long parent_rate);
289 int sifive_clk_is_enabled(struct clk_hw *hw);
290 int sifive_prci_clock_enable(struct clk_hw *hw);
291 void sifive_prci_clock_disable(struct clk_hw *hw);
292 unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
293 					    unsigned long parent_rate);
294 unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
295 					       unsigned long parent_rate);
296 unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
297 						   unsigned long parent_rate);
298 
299 #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
300