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