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