xref: /openbmc/linux/drivers/clk/x86/clk-cgu.h (revision d058fd9e)
1d058fd9eSRahul Tanwar /* SPDX-License-Identifier: GPL-2.0 */
2d058fd9eSRahul Tanwar /*
3d058fd9eSRahul Tanwar  * Copyright(c) 2020 Intel Corporation.
4d058fd9eSRahul Tanwar  * Zhu YiXin <yixin.zhu@intel.com>
5d058fd9eSRahul Tanwar  * Rahul Tanwar <rahul.tanwar@intel.com>
6d058fd9eSRahul Tanwar  */
7d058fd9eSRahul Tanwar 
8d058fd9eSRahul Tanwar #ifndef __CLK_CGU_H
9d058fd9eSRahul Tanwar #define __CLK_CGU_H
10d058fd9eSRahul Tanwar 
11d058fd9eSRahul Tanwar #include <linux/io.h>
12d058fd9eSRahul Tanwar 
13d058fd9eSRahul Tanwar struct lgm_clk_mux {
14d058fd9eSRahul Tanwar 	struct clk_hw hw;
15d058fd9eSRahul Tanwar 	void __iomem *membase;
16d058fd9eSRahul Tanwar 	unsigned int reg;
17d058fd9eSRahul Tanwar 	u8 shift;
18d058fd9eSRahul Tanwar 	u8 width;
19d058fd9eSRahul Tanwar 	unsigned long flags;
20d058fd9eSRahul Tanwar 	spinlock_t lock;
21d058fd9eSRahul Tanwar };
22d058fd9eSRahul Tanwar 
23d058fd9eSRahul Tanwar struct lgm_clk_divider {
24d058fd9eSRahul Tanwar 	struct clk_hw hw;
25d058fd9eSRahul Tanwar 	void __iomem *membase;
26d058fd9eSRahul Tanwar 	unsigned int reg;
27d058fd9eSRahul Tanwar 	u8 shift;
28d058fd9eSRahul Tanwar 	u8 width;
29d058fd9eSRahul Tanwar 	u8 shift_gate;
30d058fd9eSRahul Tanwar 	u8 width_gate;
31d058fd9eSRahul Tanwar 	unsigned long flags;
32d058fd9eSRahul Tanwar 	const struct clk_div_table *table;
33d058fd9eSRahul Tanwar 	spinlock_t lock;
34d058fd9eSRahul Tanwar };
35d058fd9eSRahul Tanwar 
36d058fd9eSRahul Tanwar struct lgm_clk_ddiv {
37d058fd9eSRahul Tanwar 	struct clk_hw hw;
38d058fd9eSRahul Tanwar 	void __iomem *membase;
39d058fd9eSRahul Tanwar 	unsigned int reg;
40d058fd9eSRahul Tanwar 	u8 shift0;
41d058fd9eSRahul Tanwar 	u8 width0;
42d058fd9eSRahul Tanwar 	u8 shift1;
43d058fd9eSRahul Tanwar 	u8 width1;
44d058fd9eSRahul Tanwar 	u8 shift2;
45d058fd9eSRahul Tanwar 	u8 width2;
46d058fd9eSRahul Tanwar 	u8 shift_gate;
47d058fd9eSRahul Tanwar 	u8 width_gate;
48d058fd9eSRahul Tanwar 	unsigned int mult;
49d058fd9eSRahul Tanwar 	unsigned int div;
50d058fd9eSRahul Tanwar 	unsigned long flags;
51d058fd9eSRahul Tanwar 	spinlock_t lock;
52d058fd9eSRahul Tanwar };
53d058fd9eSRahul Tanwar 
54d058fd9eSRahul Tanwar struct lgm_clk_gate {
55d058fd9eSRahul Tanwar 	struct clk_hw hw;
56d058fd9eSRahul Tanwar 	void __iomem *membase;
57d058fd9eSRahul Tanwar 	unsigned int reg;
58d058fd9eSRahul Tanwar 	u8 shift;
59d058fd9eSRahul Tanwar 	unsigned long flags;
60d058fd9eSRahul Tanwar 	spinlock_t lock;
61d058fd9eSRahul Tanwar };
62d058fd9eSRahul Tanwar 
63d058fd9eSRahul Tanwar enum lgm_clk_type {
64d058fd9eSRahul Tanwar 	CLK_TYPE_FIXED,
65d058fd9eSRahul Tanwar 	CLK_TYPE_MUX,
66d058fd9eSRahul Tanwar 	CLK_TYPE_DIVIDER,
67d058fd9eSRahul Tanwar 	CLK_TYPE_FIXED_FACTOR,
68d058fd9eSRahul Tanwar 	CLK_TYPE_GATE,
69d058fd9eSRahul Tanwar 	CLK_TYPE_NONE,
70d058fd9eSRahul Tanwar };
71d058fd9eSRahul Tanwar 
72d058fd9eSRahul Tanwar /**
73d058fd9eSRahul Tanwar  * struct lgm_clk_provider
74d058fd9eSRahul Tanwar  * @membase: IO mem base address for CGU.
75d058fd9eSRahul Tanwar  * @np: device node
76d058fd9eSRahul Tanwar  * @dev: device
77d058fd9eSRahul Tanwar  * @clk_data: array of hw clocks and clk number.
78d058fd9eSRahul Tanwar  */
79d058fd9eSRahul Tanwar struct lgm_clk_provider {
80d058fd9eSRahul Tanwar 	void __iomem *membase;
81d058fd9eSRahul Tanwar 	struct device_node *np;
82d058fd9eSRahul Tanwar 	struct device *dev;
83d058fd9eSRahul Tanwar 	struct clk_hw_onecell_data clk_data;
84d058fd9eSRahul Tanwar 	spinlock_t lock;
85d058fd9eSRahul Tanwar };
86d058fd9eSRahul Tanwar 
87d058fd9eSRahul Tanwar enum pll_type {
88d058fd9eSRahul Tanwar 	TYPE_ROPLL,
89d058fd9eSRahul Tanwar 	TYPE_LJPLL,
90d058fd9eSRahul Tanwar 	TYPE_NONE,
91d058fd9eSRahul Tanwar };
92d058fd9eSRahul Tanwar 
93d058fd9eSRahul Tanwar struct lgm_clk_pll {
94d058fd9eSRahul Tanwar 	struct clk_hw hw;
95d058fd9eSRahul Tanwar 	void __iomem *membase;
96d058fd9eSRahul Tanwar 	unsigned int reg;
97d058fd9eSRahul Tanwar 	unsigned long flags;
98d058fd9eSRahul Tanwar 	enum pll_type type;
99d058fd9eSRahul Tanwar 	spinlock_t lock;
100d058fd9eSRahul Tanwar };
101d058fd9eSRahul Tanwar 
102d058fd9eSRahul Tanwar /**
103d058fd9eSRahul Tanwar  * struct lgm_pll_clk_data
104d058fd9eSRahul Tanwar  * @id: platform specific id of the clock.
105d058fd9eSRahul Tanwar  * @name: name of this pll clock.
106d058fd9eSRahul Tanwar  * @parent_data: parent clock data.
107d058fd9eSRahul Tanwar  * @num_parents: number of parents.
108d058fd9eSRahul Tanwar  * @flags: optional flags for basic clock.
109d058fd9eSRahul Tanwar  * @type: platform type of pll.
110d058fd9eSRahul Tanwar  * @reg: offset of the register.
111d058fd9eSRahul Tanwar  */
112d058fd9eSRahul Tanwar struct lgm_pll_clk_data {
113d058fd9eSRahul Tanwar 	unsigned int id;
114d058fd9eSRahul Tanwar 	const char *name;
115d058fd9eSRahul Tanwar 	const struct clk_parent_data *parent_data;
116d058fd9eSRahul Tanwar 	u8 num_parents;
117d058fd9eSRahul Tanwar 	unsigned long flags;
118d058fd9eSRahul Tanwar 	enum pll_type type;
119d058fd9eSRahul Tanwar 	int reg;
120d058fd9eSRahul Tanwar };
121d058fd9eSRahul Tanwar 
122d058fd9eSRahul Tanwar #define LGM_PLL(_id, _name, _pdata, _flags,		\
123d058fd9eSRahul Tanwar 		_reg, _type)				\
124d058fd9eSRahul Tanwar 	{						\
125d058fd9eSRahul Tanwar 		.id = _id,				\
126d058fd9eSRahul Tanwar 		.name = _name,				\
127d058fd9eSRahul Tanwar 		.parent_data = _pdata,			\
128d058fd9eSRahul Tanwar 		.num_parents = ARRAY_SIZE(_pdata),	\
129d058fd9eSRahul Tanwar 		.flags = _flags,			\
130d058fd9eSRahul Tanwar 		.reg = _reg,				\
131d058fd9eSRahul Tanwar 		.type = _type,				\
132d058fd9eSRahul Tanwar 	}
133d058fd9eSRahul Tanwar 
134d058fd9eSRahul Tanwar struct lgm_clk_ddiv_data {
135d058fd9eSRahul Tanwar 	unsigned int id;
136d058fd9eSRahul Tanwar 	const char *name;
137d058fd9eSRahul Tanwar 	const struct clk_parent_data *parent_data;
138d058fd9eSRahul Tanwar 	u8 flags;
139d058fd9eSRahul Tanwar 	unsigned long div_flags;
140d058fd9eSRahul Tanwar 	unsigned int reg;
141d058fd9eSRahul Tanwar 	u8 shift0;
142d058fd9eSRahul Tanwar 	u8 width0;
143d058fd9eSRahul Tanwar 	u8 shift1;
144d058fd9eSRahul Tanwar 	u8 width1;
145d058fd9eSRahul Tanwar 	u8 shift_gate;
146d058fd9eSRahul Tanwar 	u8 width_gate;
147d058fd9eSRahul Tanwar 	u8 ex_shift;
148d058fd9eSRahul Tanwar 	u8 ex_width;
149d058fd9eSRahul Tanwar };
150d058fd9eSRahul Tanwar 
151d058fd9eSRahul Tanwar #define LGM_DDIV(_id, _name, _pname, _flags, _reg,		\
152d058fd9eSRahul Tanwar 		 _shft0, _wdth0, _shft1, _wdth1,		\
153d058fd9eSRahul Tanwar 		 _shft_gate, _wdth_gate, _xshft, _df)		\
154d058fd9eSRahul Tanwar 	{							\
155d058fd9eSRahul Tanwar 		.id = _id,					\
156d058fd9eSRahul Tanwar 		.name = _name,					\
157d058fd9eSRahul Tanwar 		.parent_data = &(const struct clk_parent_data){	\
158d058fd9eSRahul Tanwar 			.fw_name = _pname,			\
159d058fd9eSRahul Tanwar 			.name = _pname,				\
160d058fd9eSRahul Tanwar 		},						\
161d058fd9eSRahul Tanwar 		.flags = _flags,				\
162d058fd9eSRahul Tanwar 		.reg = _reg,					\
163d058fd9eSRahul Tanwar 		.shift0 = _shft0,				\
164d058fd9eSRahul Tanwar 		.width0 = _wdth0,				\
165d058fd9eSRahul Tanwar 		.shift1 = _shft1,				\
166d058fd9eSRahul Tanwar 		.width1 = _wdth1,				\
167d058fd9eSRahul Tanwar 		.shift_gate = _shft_gate,			\
168d058fd9eSRahul Tanwar 		.width_gate = _wdth_gate,			\
169d058fd9eSRahul Tanwar 		.ex_shift = _xshft,				\
170d058fd9eSRahul Tanwar 		.ex_width = 1,					\
171d058fd9eSRahul Tanwar 		.div_flags = _df,				\
172d058fd9eSRahul Tanwar 	}
173d058fd9eSRahul Tanwar 
174d058fd9eSRahul Tanwar struct lgm_clk_branch {
175d058fd9eSRahul Tanwar 	unsigned int id;
176d058fd9eSRahul Tanwar 	enum lgm_clk_type type;
177d058fd9eSRahul Tanwar 	const char *name;
178d058fd9eSRahul Tanwar 	const struct clk_parent_data *parent_data;
179d058fd9eSRahul Tanwar 	u8 num_parents;
180d058fd9eSRahul Tanwar 	unsigned long flags;
181d058fd9eSRahul Tanwar 	unsigned int mux_off;
182d058fd9eSRahul Tanwar 	u8 mux_shift;
183d058fd9eSRahul Tanwar 	u8 mux_width;
184d058fd9eSRahul Tanwar 	unsigned long mux_flags;
185d058fd9eSRahul Tanwar 	unsigned int mux_val;
186d058fd9eSRahul Tanwar 	unsigned int div_off;
187d058fd9eSRahul Tanwar 	u8 div_shift;
188d058fd9eSRahul Tanwar 	u8 div_width;
189d058fd9eSRahul Tanwar 	u8 div_shift_gate;
190d058fd9eSRahul Tanwar 	u8 div_width_gate;
191d058fd9eSRahul Tanwar 	unsigned long div_flags;
192d058fd9eSRahul Tanwar 	unsigned int div_val;
193d058fd9eSRahul Tanwar 	const struct clk_div_table *div_table;
194d058fd9eSRahul Tanwar 	unsigned int gate_off;
195d058fd9eSRahul Tanwar 	u8 gate_shift;
196d058fd9eSRahul Tanwar 	unsigned long gate_flags;
197d058fd9eSRahul Tanwar 	unsigned int gate_val;
198d058fd9eSRahul Tanwar 	unsigned int mult;
199d058fd9eSRahul Tanwar 	unsigned int div;
200d058fd9eSRahul Tanwar };
201d058fd9eSRahul Tanwar 
202d058fd9eSRahul Tanwar /* clock flags definition */
203d058fd9eSRahul Tanwar #define CLOCK_FLAG_VAL_INIT	BIT(16)
204d058fd9eSRahul Tanwar #define MUX_CLK_SW		BIT(17)
205d058fd9eSRahul Tanwar 
206d058fd9eSRahul Tanwar #define LGM_MUX(_id, _name, _pdata, _f, _reg,		\
207d058fd9eSRahul Tanwar 		_shift, _width, _cf, _v)		\
208d058fd9eSRahul Tanwar 	{						\
209d058fd9eSRahul Tanwar 		.id = _id,				\
210d058fd9eSRahul Tanwar 		.type = CLK_TYPE_MUX,			\
211d058fd9eSRahul Tanwar 		.name = _name,				\
212d058fd9eSRahul Tanwar 		.parent_data = _pdata,			\
213d058fd9eSRahul Tanwar 		.num_parents = ARRAY_SIZE(_pdata),	\
214d058fd9eSRahul Tanwar 		.flags = _f,				\
215d058fd9eSRahul Tanwar 		.mux_off = _reg,			\
216d058fd9eSRahul Tanwar 		.mux_shift = _shift,			\
217d058fd9eSRahul Tanwar 		.mux_width = _width,			\
218d058fd9eSRahul Tanwar 		.mux_flags = _cf,			\
219d058fd9eSRahul Tanwar 		.mux_val = _v,				\
220d058fd9eSRahul Tanwar 	}
221d058fd9eSRahul Tanwar 
222d058fd9eSRahul Tanwar #define LGM_DIV(_id, _name, _pname, _f, _reg, _shift, _width,	\
223d058fd9eSRahul Tanwar 		_shift_gate, _width_gate, _cf, _v, _dtable)	\
224d058fd9eSRahul Tanwar 	{							\
225d058fd9eSRahul Tanwar 		.id = _id,					\
226d058fd9eSRahul Tanwar 		.type = CLK_TYPE_DIVIDER,			\
227d058fd9eSRahul Tanwar 		.name = _name,					\
228d058fd9eSRahul Tanwar 		.parent_data = &(const struct clk_parent_data){	\
229d058fd9eSRahul Tanwar 			.fw_name = _pname,			\
230d058fd9eSRahul Tanwar 			.name = _pname,				\
231d058fd9eSRahul Tanwar 		},						\
232d058fd9eSRahul Tanwar 		.num_parents = 1,				\
233d058fd9eSRahul Tanwar 		.flags = _f,					\
234d058fd9eSRahul Tanwar 		.div_off = _reg,				\
235d058fd9eSRahul Tanwar 		.div_shift = _shift,				\
236d058fd9eSRahul Tanwar 		.div_width = _width,				\
237d058fd9eSRahul Tanwar 		.div_shift_gate = _shift_gate,			\
238d058fd9eSRahul Tanwar 		.div_width_gate = _width_gate,			\
239d058fd9eSRahul Tanwar 		.div_flags = _cf,				\
240d058fd9eSRahul Tanwar 		.div_val = _v,					\
241d058fd9eSRahul Tanwar 		.div_table = _dtable,				\
242d058fd9eSRahul Tanwar 	}
243d058fd9eSRahul Tanwar 
244d058fd9eSRahul Tanwar #define LGM_GATE(_id, _name, _pname, _f, _reg,			\
245d058fd9eSRahul Tanwar 		 _shift, _cf, _v)				\
246d058fd9eSRahul Tanwar 	{							\
247d058fd9eSRahul Tanwar 		.id = _id,					\
248d058fd9eSRahul Tanwar 		.type = CLK_TYPE_GATE,				\
249d058fd9eSRahul Tanwar 		.name = _name,					\
250d058fd9eSRahul Tanwar 		.parent_data = &(const struct clk_parent_data){	\
251d058fd9eSRahul Tanwar 			.fw_name = _pname,			\
252d058fd9eSRahul Tanwar 			.name = _pname,				\
253d058fd9eSRahul Tanwar 		},						\
254d058fd9eSRahul Tanwar 		.num_parents = !_pname ? 0 : 1,			\
255d058fd9eSRahul Tanwar 		.flags = _f,					\
256d058fd9eSRahul Tanwar 		.gate_off = _reg,				\
257d058fd9eSRahul Tanwar 		.gate_shift = _shift,				\
258d058fd9eSRahul Tanwar 		.gate_flags = _cf,				\
259d058fd9eSRahul Tanwar 		.gate_val = _v,					\
260d058fd9eSRahul Tanwar 	}
261d058fd9eSRahul Tanwar 
262d058fd9eSRahul Tanwar #define LGM_FIXED(_id, _name, _pname, _f, _reg,			\
263d058fd9eSRahul Tanwar 		  _shift, _width, _cf, _freq, _v)		\
264d058fd9eSRahul Tanwar 	{							\
265d058fd9eSRahul Tanwar 		.id = _id,					\
266d058fd9eSRahul Tanwar 		.type = CLK_TYPE_FIXED,				\
267d058fd9eSRahul Tanwar 		.name = _name,					\
268d058fd9eSRahul Tanwar 		.parent_data = &(const struct clk_parent_data){	\
269d058fd9eSRahul Tanwar 			.fw_name = _pname,			\
270d058fd9eSRahul Tanwar 			.name = _pname,				\
271d058fd9eSRahul Tanwar 		},						\
272d058fd9eSRahul Tanwar 		.num_parents = !_pname ? 0 : 1,			\
273d058fd9eSRahul Tanwar 		.flags = _f,					\
274d058fd9eSRahul Tanwar 		.div_off = _reg,				\
275d058fd9eSRahul Tanwar 		.div_shift = _shift,				\
276d058fd9eSRahul Tanwar 		.div_width = _width,				\
277d058fd9eSRahul Tanwar 		.div_flags = _cf,				\
278d058fd9eSRahul Tanwar 		.div_val = _v,					\
279d058fd9eSRahul Tanwar 		.mux_flags = _freq,				\
280d058fd9eSRahul Tanwar 	}
281d058fd9eSRahul Tanwar 
282d058fd9eSRahul Tanwar #define LGM_FIXED_FACTOR(_id, _name, _pname, _f, _reg,		\
283d058fd9eSRahul Tanwar 			 _shift, _width, _cf, _v, _m, _d)	\
284d058fd9eSRahul Tanwar 	{							\
285d058fd9eSRahul Tanwar 		.id = _id,					\
286d058fd9eSRahul Tanwar 		.type = CLK_TYPE_FIXED_FACTOR,			\
287d058fd9eSRahul Tanwar 		.name = _name,					\
288d058fd9eSRahul Tanwar 		.parent_data = &(const struct clk_parent_data){	\
289d058fd9eSRahul Tanwar 			.fw_name = _pname,			\
290d058fd9eSRahul Tanwar 			.name = _pname,				\
291d058fd9eSRahul Tanwar 		},						\
292d058fd9eSRahul Tanwar 		.num_parents = 1,				\
293d058fd9eSRahul Tanwar 		.flags = _f,					\
294d058fd9eSRahul Tanwar 		.div_off = _reg,				\
295d058fd9eSRahul Tanwar 		.div_shift = _shift,				\
296d058fd9eSRahul Tanwar 		.div_width = _width,				\
297d058fd9eSRahul Tanwar 		.div_flags = _cf,				\
298d058fd9eSRahul Tanwar 		.div_val = _v,					\
299d058fd9eSRahul Tanwar 		.mult = _m,					\
300d058fd9eSRahul Tanwar 		.div = _d,					\
301d058fd9eSRahul Tanwar 	}
302d058fd9eSRahul Tanwar 
303d058fd9eSRahul Tanwar static inline void lgm_set_clk_val(void __iomem *membase, u32 reg,
304d058fd9eSRahul Tanwar 				   u8 shift, u8 width, u32 set_val)
305d058fd9eSRahul Tanwar {
306d058fd9eSRahul Tanwar 	u32 mask = (GENMASK(width - 1, 0) << shift);
307d058fd9eSRahul Tanwar 	u32 regval;
308d058fd9eSRahul Tanwar 
309d058fd9eSRahul Tanwar 	regval = readl(membase + reg);
310d058fd9eSRahul Tanwar 	regval = (regval & ~mask) | ((set_val << shift) & mask);
311d058fd9eSRahul Tanwar 	writel(regval, membase + reg);
312d058fd9eSRahul Tanwar }
313d058fd9eSRahul Tanwar 
314d058fd9eSRahul Tanwar static inline u32 lgm_get_clk_val(void __iomem *membase, u32 reg,
315d058fd9eSRahul Tanwar 				  u8 shift, u8 width)
316d058fd9eSRahul Tanwar {
317d058fd9eSRahul Tanwar 	u32 mask = (GENMASK(width - 1, 0) << shift);
318d058fd9eSRahul Tanwar 	u32 val;
319d058fd9eSRahul Tanwar 
320d058fd9eSRahul Tanwar 	val = readl(membase + reg);
321d058fd9eSRahul Tanwar 	val = (val & mask) >> shift;
322d058fd9eSRahul Tanwar 
323d058fd9eSRahul Tanwar 	return val;
324d058fd9eSRahul Tanwar }
325d058fd9eSRahul Tanwar 
326d058fd9eSRahul Tanwar int lgm_clk_register_branches(struct lgm_clk_provider *ctx,
327d058fd9eSRahul Tanwar 			      const struct lgm_clk_branch *list,
328d058fd9eSRahul Tanwar 			      unsigned int nr_clk);
329d058fd9eSRahul Tanwar int lgm_clk_register_plls(struct lgm_clk_provider *ctx,
330d058fd9eSRahul Tanwar 			  const struct lgm_pll_clk_data *list,
331d058fd9eSRahul Tanwar 			  unsigned int nr_clk);
332d058fd9eSRahul Tanwar int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx,
333d058fd9eSRahul Tanwar 			  const struct lgm_clk_ddiv_data *list,
334d058fd9eSRahul Tanwar 			  unsigned int nr_clk);
335d058fd9eSRahul Tanwar #endif	/* __CLK_CGU_H */
336