1/*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * Copyright (c) 2013 Linaro Ltd.
4 * Author: Thomas Abraham <thomas.ab@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Common Clock Framework support for all Samsung platforms
11*/
12
13#ifndef __SAMSUNG_CLK_H
14#define __SAMSUNG_CLK_H
15
16#include <linux/clkdev.h>
17#include <linux/clk-provider.h>
18#include "clk-pll.h"
19
20/**
21 * struct samsung_clk_provider: information about clock provider
22 * @reg_base: virtual address for the register base.
23 * @clk_data: holds clock related data like clk* and number of clocks.
24 * @lock: maintains exclusion between callbacks for a given clock-provider.
25 */
26struct samsung_clk_provider {
27	void __iomem *reg_base;
28	struct clk_onecell_data clk_data;
29	spinlock_t lock;
30};
31
32/**
33 * struct samsung_clock_alias: information about mux clock
34 * @id: platform specific id of the clock.
35 * @dev_name: name of the device to which this clock belongs.
36 * @alias: optional clock alias name to be assigned to this clock.
37 */
38struct samsung_clock_alias {
39	unsigned int		id;
40	const char		*dev_name;
41	const char		*alias;
42};
43
44#define ALIAS(_id, dname, a)	\
45	{							\
46		.id		= _id,				\
47		.dev_name	= dname,			\
48		.alias		= a,				\
49	}
50
51#define MHZ (1000 * 1000)
52
53/**
54 * struct samsung_fixed_rate_clock: information about fixed-rate clock
55 * @id: platform specific id of the clock.
56 * @name: name of this fixed-rate clock.
57 * @parent_name: optional parent clock name.
58 * @flags: optional fixed-rate clock flags.
59 * @fixed-rate: fixed clock rate of this clock.
60 */
61struct samsung_fixed_rate_clock {
62	unsigned int		id;
63	char			*name;
64	const char		*parent_name;
65	unsigned long		flags;
66	unsigned long		fixed_rate;
67};
68
69#define FRATE(_id, cname, pname, f, frate)		\
70	{						\
71		.id		= _id,			\
72		.name		= cname,		\
73		.parent_name	= pname,		\
74		.flags		= f,			\
75		.fixed_rate	= frate,		\
76	}
77
78/*
79 * struct samsung_fixed_factor_clock: information about fixed-factor clock
80 * @id: platform specific id of the clock.
81 * @name: name of this fixed-factor clock.
82 * @parent_name: parent clock name.
83 * @mult: fixed multiplication factor.
84 * @div: fixed division factor.
85 * @flags: optional fixed-factor clock flags.
86 */
87struct samsung_fixed_factor_clock {
88	unsigned int		id;
89	char			*name;
90	const char		*parent_name;
91	unsigned long		mult;
92	unsigned long		div;
93	unsigned long		flags;
94};
95
96#define FFACTOR(_id, cname, pname, m, d, f)		\
97	{						\
98		.id		= _id,			\
99		.name		= cname,		\
100		.parent_name	= pname,		\
101		.mult		= m,			\
102		.div		= d,			\
103		.flags		= f,			\
104	}
105
106/**
107 * struct samsung_mux_clock: information about mux clock
108 * @id: platform specific id of the clock.
109 * @dev_name: name of the device to which this clock belongs.
110 * @name: name of this mux clock.
111 * @parent_names: array of pointer to parent clock names.
112 * @num_parents: number of parents listed in @parent_names.
113 * @flags: optional flags for basic clock.
114 * @offset: offset of the register for configuring the mux.
115 * @shift: starting bit location of the mux control bit-field in @reg.
116 * @width: width of the mux control bit-field in @reg.
117 * @mux_flags: flags for mux-type clock.
118 * @alias: optional clock alias name to be assigned to this clock.
119 */
120struct samsung_mux_clock {
121	unsigned int		id;
122	const char		*dev_name;
123	const char		*name;
124	const char		**parent_names;
125	u8			num_parents;
126	unsigned long		flags;
127	unsigned long		offset;
128	u8			shift;
129	u8			width;
130	u8			mux_flags;
131	const char		*alias;
132};
133
134#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a)	\
135	{							\
136		.id		= _id,				\
137		.dev_name	= dname,			\
138		.name		= cname,			\
139		.parent_names	= pnames,			\
140		.num_parents	= ARRAY_SIZE(pnames),		\
141		.flags		= (f) | CLK_SET_RATE_NO_REPARENT, \
142		.offset		= o,				\
143		.shift		= s,				\
144		.width		= w,				\
145		.mux_flags	= mf,				\
146		.alias		= a,				\
147	}
148
149#define MUX(_id, cname, pnames, o, s, w)			\
150	__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
151
152#define MUX_A(_id, cname, pnames, o, s, w, a)			\
153	__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
154
155#define MUX_F(_id, cname, pnames, o, s, w, f, mf)		\
156	__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
157
158#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a)		\
159	__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a)
160
161/**
162 * @id: platform specific id of the clock.
163 * struct samsung_div_clock: information about div clock
164 * @dev_name: name of the device to which this clock belongs.
165 * @name: name of this div clock.
166 * @parent_name: name of the parent clock.
167 * @flags: optional flags for basic clock.
168 * @offset: offset of the register for configuring the div.
169 * @shift: starting bit location of the div control bit-field in @reg.
170 * @div_flags: flags for div-type clock.
171 * @alias: optional clock alias name to be assigned to this clock.
172 */
173struct samsung_div_clock {
174	unsigned int		id;
175	const char		*dev_name;
176	const char		*name;
177	const char		*parent_name;
178	unsigned long		flags;
179	unsigned long		offset;
180	u8			shift;
181	u8			width;
182	u8			div_flags;
183	const char		*alias;
184	struct clk_div_table	*table;
185};
186
187#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t)	\
188	{							\
189		.id		= _id,				\
190		.dev_name	= dname,			\
191		.name		= cname,			\
192		.parent_name	= pname,			\
193		.flags		= f,				\
194		.offset		= o,				\
195		.shift		= s,				\
196		.width		= w,				\
197		.div_flags	= df,				\
198		.alias		= a,				\
199		.table		= t,				\
200	}
201
202#define DIV(_id, cname, pname, o, s, w)				\
203	__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
204
205#define DIV_A(_id, cname, pname, o, s, w, a)			\
206	__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
207
208#define DIV_F(_id, cname, pname, o, s, w, f, df)		\
209	__DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
210
211#define DIV_T(_id, cname, pname, o, s, w, t)			\
212	__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
213
214/**
215 * struct samsung_gate_clock: information about gate clock
216 * @id: platform specific id of the clock.
217 * @dev_name: name of the device to which this clock belongs.
218 * @name: name of this gate clock.
219 * @parent_name: name of the parent clock.
220 * @flags: optional flags for basic clock.
221 * @offset: offset of the register for configuring the gate.
222 * @bit_idx: bit index of the gate control bit-field in @reg.
223 * @gate_flags: flags for gate-type clock.
224 * @alias: optional clock alias name to be assigned to this clock.
225 */
226struct samsung_gate_clock {
227	unsigned int		id;
228	const char		*dev_name;
229	const char		*name;
230	const char		*parent_name;
231	unsigned long		flags;
232	unsigned long		offset;
233	u8			bit_idx;
234	u8			gate_flags;
235	const char		*alias;
236};
237
238#define __GATE(_id, dname, cname, pname, o, b, f, gf, a)	\
239	{							\
240		.id		= _id,				\
241		.dev_name	= dname,			\
242		.name		= cname,			\
243		.parent_name	= pname,			\
244		.flags		= f,				\
245		.offset		= o,				\
246		.bit_idx	= b,				\
247		.gate_flags	= gf,				\
248		.alias		= a,				\
249	}
250
251#define GATE(_id, cname, pname, o, b, f, gf)			\
252	__GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
253
254#define GATE_A(_id, cname, pname, o, b, f, gf, a)		\
255	__GATE(_id, NULL, cname, pname, o, b, f, gf, a)
256
257#define GATE_D(_id, dname, cname, pname, o, b, f, gf)		\
258	__GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
259
260#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a)	\
261	__GATE(_id, dname, cname, pname, o, b, f, gf, a)
262
263#define PNAME(x) static const char *x[] __initdata
264
265/**
266 * struct samsung_clk_reg_dump: register dump of clock controller registers.
267 * @offset: clock register offset from the controller base address.
268 * @value: the value to be register at offset.
269 */
270struct samsung_clk_reg_dump {
271	u32	offset;
272	u32	value;
273};
274
275/**
276 * struct samsung_pll_clock: information about pll clock
277 * @id: platform specific id of the clock.
278 * @dev_name: name of the device to which this clock belongs.
279 * @name: name of this pll clock.
280 * @parent_name: name of the parent clock.
281 * @flags: optional flags for basic clock.
282 * @con_offset: offset of the register for configuring the PLL.
283 * @lock_offset: offset of the register for locking the PLL.
284 * @type: Type of PLL to be registered.
285 * @alias: optional clock alias name to be assigned to this clock.
286 */
287struct samsung_pll_clock {
288	unsigned int		id;
289	const char		*dev_name;
290	const char		*name;
291	const char		*parent_name;
292	unsigned long		flags;
293	int			con_offset;
294	int			lock_offset;
295	enum samsung_pll_type	type;
296	const struct samsung_pll_rate_table *rate_table;
297	const char              *alias;
298};
299
300#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con,	\
301		_rtable, _alias)					\
302	{								\
303		.id		= _id,					\
304		.type		= _typ,					\
305		.dev_name	= _dname,				\
306		.name		= _name,				\
307		.parent_name	= _pname,				\
308		.flags		= CLK_GET_RATE_NOCACHE,			\
309		.con_offset	= _con,					\
310		.lock_offset	= _lock,				\
311		.rate_table	= _rtable,				\
312		.alias		= _alias,				\
313	}
314
315#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable)	\
316	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
317		_lock, _con, _rtable, _name)
318
319#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
320	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
321		_lock, _con, _rtable, _alias)
322
323struct samsung_clock_reg_cache {
324	struct list_head node;
325	void __iomem *reg_base;
326	struct samsung_clk_reg_dump *rdump;
327	unsigned int rd_num;
328};
329
330struct samsung_cmu_info {
331	/* list of pll clocks and respective count */
332	struct samsung_pll_clock *pll_clks;
333	unsigned int nr_pll_clks;
334	/* list of mux clocks and respective count */
335	struct samsung_mux_clock *mux_clks;
336	unsigned int nr_mux_clks;
337	/* list of div clocks and respective count */
338	struct samsung_div_clock *div_clks;
339	unsigned int nr_div_clks;
340	/* list of gate clocks and respective count */
341	struct samsung_gate_clock *gate_clks;
342	unsigned int nr_gate_clks;
343	/* list of fixed clocks and respective count */
344	struct samsung_fixed_rate_clock *fixed_clks;
345	unsigned int nr_fixed_clks;
346	/* list of fixed factor clocks and respective count */
347	struct samsung_fixed_factor_clock *fixed_factor_clks;
348	unsigned int nr_fixed_factor_clks;
349	/* total number of clocks with IDs assigned*/
350	unsigned int nr_clk_ids;
351
352	/* list and number of clocks registers */
353	unsigned long *clk_regs;
354	unsigned int nr_clk_regs;
355};
356
357extern struct samsung_clk_provider *__init samsung_clk_init(
358			struct device_node *np, void __iomem *base,
359			unsigned long nr_clks);
360extern void __init samsung_clk_of_add_provider(struct device_node *np,
361			struct samsung_clk_provider *ctx);
362extern void __init samsung_clk_of_register_fixed_ext(
363			struct samsung_clk_provider *ctx,
364			struct samsung_fixed_rate_clock *fixed_rate_clk,
365			unsigned int nr_fixed_rate_clk,
366			const struct of_device_id *clk_matches);
367
368extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
369			struct clk *clk, unsigned int id);
370
371extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
372			struct samsung_clock_alias *list,
373			unsigned int nr_clk);
374extern void __init samsung_clk_register_fixed_rate(
375			struct samsung_clk_provider *ctx,
376			struct samsung_fixed_rate_clock *clk_list,
377			unsigned int nr_clk);
378extern void __init samsung_clk_register_fixed_factor(
379			struct samsung_clk_provider *ctx,
380			struct samsung_fixed_factor_clock *list,
381			unsigned int nr_clk);
382extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
383			struct samsung_mux_clock *clk_list,
384			unsigned int nr_clk);
385extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
386			struct samsung_div_clock *clk_list,
387			unsigned int nr_clk);
388extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
389			struct samsung_gate_clock *clk_list,
390			unsigned int nr_clk);
391extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
392			struct samsung_pll_clock *pll_list,
393			unsigned int nr_clk, void __iomem *base);
394
395extern struct samsung_clk_provider __init *samsung_cmu_register_one(
396			struct device_node *,
397			struct samsung_cmu_info *);
398
399extern unsigned long _get_rate(const char *clk_name);
400
401extern void samsung_clk_save(void __iomem *base,
402			struct samsung_clk_reg_dump *rd,
403			unsigned int num_regs);
404extern void samsung_clk_restore(void __iomem *base,
405			const struct samsung_clk_reg_dump *rd,
406			unsigned int num_regs);
407extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
408			const unsigned long *rdump,
409			unsigned long nr_rdump);
410
411#endif /* __SAMSUNG_CLK_H */
412