1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020-2021 SiFive, Inc.
4  * Wesley Terpstra
5  * Paul Walmsley
6  * Zong Li
7  * Pragnesh Patel
8  */
9 
10 #ifndef __SIFIVE_CLK_SIFIVE_PRCI_H
11 #define __SIFIVE_CLK_SIFIVE_PRCI_H
12 
13 #include <clk.h>
14 #include <linux/clk/analogbits-wrpll-cln28hpc.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 /* PCIEAUXCFG1 */
71 #define PRCI_PCIEAUXCFG1_OFFSET		0x14
72 #define PRCI_PCIEAUXCFG1_SHIFT		0
73 #define PRCI_PCIEAUXCFG1_MASK		(0x1 << PRCI_PCIEAUXCFG1_SHIFT)
74 
75 /* GEMGXLPLLCFG0 */
76 #define PRCI_GEMGXLPLLCFG0_OFFSET	0x1c
77 #define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT	0
78 #define PRCI_GEMGXLPLLCFG0_DIVR_MASK	\
79 			(0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
80 #define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT	6
81 #define PRCI_GEMGXLPLLCFG0_DIVF_MASK	\
82 			(0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
83 #define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT	15
84 #define PRCI_GEMGXLPLLCFG0_DIVQ_MASK	(0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
85 #define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT	18
86 #define PRCI_GEMGXLPLLCFG0_RANGE_MASK	\
87 			(0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
88 #define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT	24
89 #define PRCI_GEMGXLPLLCFG0_BYPASS_MASK	\
90 			(0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
91 #define PRCI_GEMGXLPLLCFG0_FSE_SHIFT	25
92 #define PRCI_GEMGXLPLLCFG0_FSE_MASK	\
93 			(0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
94 #define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT	31
95 #define PRCI_GEMGXLPLLCFG0_LOCK_MASK	(0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
96 
97 /* GEMGXLPLLCFG1 */
98 #define PRCI_GEMGXLPLLCFG1_OFFSET	0x20
99 #define PRCI_GEMGXLPLLCFG1_CKE_SHIFT	31
100 #define PRCI_GEMGXLPLLCFG1_CKE_MASK	(0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
101 
102 /* CORECLKSEL */
103 #define PRCI_CORECLKSEL_OFFSET		0x24
104 #define PRCI_CORECLKSEL_CORECLKSEL_SHIFT	0
105 #define PRCI_CORECLKSEL_CORECLKSEL_MASK \
106 			(0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
107 
108 /* DEVICESRESETREG */
109 #define PRCI_DEVICESRESETREG_OFFSET	0x28
110 #define PRCI_DEVICERESETCNT	6
111 
112 /* CLKMUXSTATUSREG */
113 #define PRCI_CLKMUXSTATUSREG_OFFSET	0x2c
114 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT	1
115 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
116 			(0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
117 
118 /* CLTXPLLCFG0 */
119 #define PRCI_CLTXPLLCFG0_OFFSET		0x30
120 #define PRCI_CLTXPLLCFG0_DIVR_SHIFT	0
121 #define PRCI_CLTXPLLCFG0_DIVR_MASK	(0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)
122 #define PRCI_CLTXPLLCFG0_DIVF_SHIFT	6
123 #define PRCI_CLTXPLLCFG0_DIVF_MASK	(0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)
124 #define PRCI_CLTXPLLCFG0_DIVQ_SHIFT	15
125 #define PRCI_CLTXPLLCFG0_DIVQ_MASK	(0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)
126 #define PRCI_CLTXPLLCFG0_RANGE_SHIFT	18
127 #define PRCI_CLTXPLLCFG0_RANGE_MASK	(0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)
128 #define PRCI_CLTXPLLCFG0_BYPASS_SHIFT	24
129 #define PRCI_CLTXPLLCFG0_BYPASS_MASK	(0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)
130 #define PRCI_CLTXPLLCFG0_FSE_SHIFT	25
131 #define PRCI_CLTXPLLCFG0_FSE_MASK	(0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)
132 #define PRCI_CLTXPLLCFG0_LOCK_SHIFT	31
133 #define PRCI_CLTXPLLCFG0_LOCK_MASK	(0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)
134 
135 /* CLTXPLLCFG1 */
136 #define PRCI_CLTXPLLCFG1_OFFSET		0x34
137 #define PRCI_CLTXPLLCFG1_CKE_SHIFT	24
138 #define PRCI_CLTXPLLCFG1_CKE_MASK	(0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)
139 
140 /* DVFSCOREPLLCFG0 */
141 #define PRCI_DVFSCOREPLLCFG0_OFFSET	0x38
142 
143 /* DVFSCOREPLLCFG1 */
144 #define PRCI_DVFSCOREPLLCFG1_OFFSET	0x3c
145 #define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT	24
146 #define PRCI_DVFSCOREPLLCFG1_CKE_MASK	(0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)
147 
148 /* COREPLLSEL */
149 #define PRCI_COREPLLSEL_OFFSET		0x40
150 #define PRCI_COREPLLSEL_COREPLLSEL_SHIFT	0
151 #define PRCI_COREPLLSEL_COREPLLSEL_MASK	\
152 		(0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)
153 
154 /* HFPCLKPLLCFG0 */
155 #define PRCI_HFPCLKPLLCFG0_OFFSET		0x50
156 #define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT		0
157 #define PRCI_HFPCLKPLL_CFG0_DIVR_MASK	\
158 		(0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)
159 #define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT		6
160 #define PRCI_HFPCLKPLL_CFG0_DIVF_MASK	\
161 		(0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)
162 #define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT		15
163 #define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK	\
164 		(0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)
165 #define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT		18
166 #define PRCI_HFPCLKPLL_CFG0_RANGE_MASK	\
167 		(0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)
168 #define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT	24
169 #define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK	\
170 		(0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)
171 #define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT		25
172 #define PRCI_HFPCLKPLL_CFG0_FSE_MASK	\
173 		(0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)
174 #define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT		31
175 #define PRCI_HFPCLKPLL_CFG0_LOCK_MASK	\
176 		(0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)
177 
178 /* HFPCLKPLLCFG1 */
179 #define PRCI_HFPCLKPLLCFG1_OFFSET		0x54
180 #define PRCI_HFPCLKPLLCFG1_CKE_SHIFT		24
181 #define PRCI_HFPCLKPLLCFG1_CKE_MASK	\
182 		(0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)
183 
184 /* HFPCLKPLLSEL */
185 #define PRCI_HFPCLKPLLSEL_OFFSET		0x58
186 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT	0
187 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK	\
188 		(0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)
189 
190 /* HFPCLKPLLDIV */
191 #define PRCI_HFPCLKPLLDIV_OFFSET		0x5c
192 
193 /* PRCIPLL */
194 #define PRCI_PRCIPLL_OFFSET			0xe0
195 
196 #define PRCI_PRCIPLL_CLTXPLL			(0x1 << 0)
197 #define PRCI_PRCIPLL_GEMGXLPLL			(0x1 << 1)
198 #define PRCI_PRCIPLL_DDRPLL			(0x1 << 2)
199 #define PRCI_PRCIPLL_HFPCLKPLL			(0x1 << 3)
200 #define PRCI_PRCIPLL_DVFSCOREPLL		(0x1 << 4)
201 #define PRCI_PRCIPLL_COREPLL			(0x1 << 5)
202 
203 /* PROCMONCFG */
204 #define PRCI_PROCMONCFG_OFFSET		0xF0
205 #define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT	24
206 #define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
207 			(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
208 
209 /*
210  * Private structures
211  */
212 
213 /**
214  * struct __prci_data - per-device-instance data
215  * @va: base virtual address of the PRCI IP block
216  * @parent: parent clk instance
217  *
218  * PRCI per-device instance data
219  */
220 struct __prci_data {
221 	void *va;
222 	struct clk parent_hfclk;
223 	struct clk parent_rtcclk;
224 };
225 
226 /**
227  * struct __prci_wrpll_data - WRPLL configuration and integration data
228  * @c: WRPLL current configuration record
229  * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
230  * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
231  * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
232  * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
233  * @release_reset: fn ptr to code to release clock reset
234  *
235  * @enable_bypass and @disable_bypass are used for WRPLL instances
236  * that contain a separate external glitchless clock mux downstream
237  * from the PLL.  The WRPLL internal bypass mux is not glitchless.
238  */
239 struct __prci_wrpll_data {
240 	struct wrpll_cfg c;
241 	void (*enable_bypass)(struct __prci_data *pd);
242 	void (*disable_bypass)(struct __prci_data *pd);
243 	u8 cfg0_offs;
244 	u8 cfg1_offs;
245 	void (*release_reset)(struct __prci_data *pd);
246 };
247 
248 /**
249  * struct __prci_clock - describes a clock device managed by PRCI
250  * @name: user-readable clock name string - should match the manual
251  * @parent_name: parent name for this clock
252  * @ops: struct __prci_clock_ops for control
253  * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
254  * @pd: PRCI-specific data associated with this clock (if not NULL)
255  *
256  * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
257  * clocks to the Linux clock infrastructure.
258  */
259 struct __prci_clock {
260 	const char *name;
261 	const char *parent_name;
262 	const struct __prci_clock_ops *ops;
263 	struct __prci_wrpll_data *pwd;
264 	struct __prci_data *pd;
265 };
266 
267 /* struct __prci_clock_ops - clock operations */
268 struct __prci_clock_ops {
269 	int (*set_rate)(struct __prci_clock *pc,
270 			unsigned long rate,
271 			unsigned long parent_rate);
272 	unsigned long (*round_rate)(struct __prci_clock *pc,
273 				    unsigned long rate,
274 				    unsigned long *parent_rate);
275 	unsigned long (*recalc_rate)(struct __prci_clock *pc,
276 				     unsigned long parent_rate);
277 	int (*enable_clk)(struct __prci_clock *pc, bool enable);
278 };
279 
280 /*
281  * struct prci_clk_desc - describes the information of clocks of each SoCs
282  * @clks: point to a array of __prci_clock
283  * @num_clks: the number of element of clks
284  */
285 struct prci_clk_desc {
286 	struct __prci_clock *clks;
287 	size_t num_clks;
288 };
289 
290 void sifive_prci_ethernet_release_reset(struct __prci_data *pd);
291 void sifive_prci_ddr_release_reset(struct __prci_data *pd);
292 void sifive_prci_cltx_release_reset(struct __prci_data *pd);
293 
294 /* Core clock mux control */
295 void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
296 void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
297 void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);
298 void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);
299 void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);
300 void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
301 void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
302 
303 unsigned long sifive_prci_wrpll_round_rate(struct __prci_clock *pc,
304 					   unsigned long rate,
305 					   unsigned long *parent_rate);
306 
307 /* Linux clock framework integration */
308 int sifive_prci_wrpll_set_rate(struct __prci_clock *pc,
309 			       unsigned long rate,
310 			       unsigned long parent_rate);
311 
312 unsigned long sifive_prci_wrpll_recalc_rate(struct __prci_clock *pc,
313 					    unsigned long parent_rate);
314 
315 unsigned long sifive_prci_tlclksel_recalc_rate(struct __prci_clock *pc,
316 					       unsigned long parent_rate);
317 
318 unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct __prci_clock *pc,
319 						   unsigned long parent_rate);
320 
321 int sifive_prci_clock_enable(struct __prci_clock *pc, bool enable);
322 
323 #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
324