Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 <linux/mod_devicetable.h>
15#include <linux/regmap.h>
16#include "clk-pll.h"
17#include "clk-cpu.h"
18
19/**
20 * struct samsung_clk_provider - information about clock provider
21 * @reg_base: virtual address for the register base
22 * @dev: clock provider device needed for runtime PM
23 * @sysreg: syscon regmap for clock-provider sysreg controller
24 * @lock: maintains exclusion between callbacks for a given clock-provider
25 * @auto_clock_gate: enable auto clk mode for all clocks in clock-provider
26 * @gate_dbg_offset: gate debug reg offset. Used for all gates in auto clk mode
27 * @option_offset: option reg offset. Enables auto mode for clock-provider
28 * @drcg_offset: dynamic root clk gate enable register offset in sysreg
29 * @memclk_offset: memclk enable register offset in sysreg
30 * @clk_data: holds clock related data like clk_hw* and number of clocks
31 */
32struct samsung_clk_provider {
33 void __iomem *reg_base;
34 struct device *dev;
35 struct regmap *sysreg;
36 spinlock_t lock;
37 bool auto_clock_gate;
38 u32 gate_dbg_offset;
39 u32 option_offset;
40 u32 drcg_offset;
41 u32 memclk_offset;
42 /* clk_data must be the last entry due to variable length 'hws' array */
43 struct clk_hw_onecell_data clk_data;
44};
45
46/**
47 * struct samsung_clock_alias - information about mux clock
48 * @id: platform specific id of the clock
49 * @dev_name: name of the device to which this clock belongs
50 * @alias: optional clock alias name to be assigned to this clock
51 */
52struct samsung_clock_alias {
53 unsigned int id;
54 const char *dev_name;
55 const char *alias;
56};
57
58#define ALIAS(_id, dname, a) \
59 { \
60 .id = _id, \
61 .dev_name = dname, \
62 .alias = a, \
63 }
64
65#define MHZ (1000 * 1000)
66
67/**
68 * struct samsung_fixed_rate_clock - information about fixed-rate clock
69 * @id: platform specific id of the clock
70 * @name: name of this fixed-rate clock
71 * @parent_name: optional parent clock name
72 * @flags: optional fixed-rate clock flags
73 * @fixed_rate: fixed clock rate of this clock
74 */
75struct samsung_fixed_rate_clock {
76 unsigned int id;
77 char *name;
78 const char *parent_name;
79 unsigned long flags;
80 unsigned long fixed_rate;
81};
82
83#define FRATE(_id, cname, pname, f, frate) \
84 { \
85 .id = _id, \
86 .name = cname, \
87 .parent_name = pname, \
88 .flags = f, \
89 .fixed_rate = frate, \
90 }
91
92/**
93 * struct samsung_fixed_factor_clock - information about fixed-factor clock
94 * @id: platform specific id of the clock
95 * @name: name of this fixed-factor clock
96 * @parent_name: parent clock name
97 * @mult: fixed multiplication factor
98 * @div: fixed division factor
99 * @flags: optional fixed-factor clock flags
100 */
101struct samsung_fixed_factor_clock {
102 unsigned int id;
103 char *name;
104 const char *parent_name;
105 unsigned long mult;
106 unsigned long div;
107 unsigned long flags;
108};
109
110#define FFACTOR(_id, cname, pname, m, d, f) \
111 { \
112 .id = _id, \
113 .name = cname, \
114 .parent_name = pname, \
115 .mult = m, \
116 .div = d, \
117 .flags = f, \
118 }
119
120/**
121 * struct samsung_mux_clock - information about mux clock
122 * @id: platform specific id of the clock
123 * @name: name of this mux clock
124 * @parent_names: array of pointer to parent clock names
125 * @num_parents: number of parents listed in @parent_names
126 * @flags: optional flags for basic clock
127 * @offset: offset of the register for configuring the mux
128 * @shift: starting bit location of the mux control bit-field in @reg
129 * @width: width of the mux control bit-field in @reg
130 * @mux_flags: flags for mux-type clock
131 */
132struct samsung_mux_clock {
133 unsigned int id;
134 const char *name;
135 const char *const *parent_names;
136 u8 num_parents;
137 unsigned long flags;
138 unsigned long offset;
139 u8 shift;
140 u8 width;
141 u8 mux_flags;
142};
143
144#define __MUX(_id, cname, pnames, o, s, w, f, mf) \
145 { \
146 .id = _id, \
147 .name = cname, \
148 .parent_names = pnames, \
149 .num_parents = ARRAY_SIZE(pnames), \
150 .flags = f, \
151 .offset = o, \
152 .shift = s, \
153 .width = w, \
154 .mux_flags = mf, \
155 }
156
157#define MUX(_id, cname, pnames, o, s, w) \
158 __MUX(_id, cname, pnames, o, s, w, CLK_SET_RATE_NO_REPARENT, 0)
159
160#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
161 __MUX(_id, cname, pnames, o, s, w, (f) | CLK_SET_RATE_NO_REPARENT, mf)
162
163/* Used by MUX clocks where reparenting on clock rate change is allowed. */
164#define nMUX(_id, cname, pnames, o, s, w) \
165 __MUX(_id, cname, pnames, o, s, w, 0, 0)
166
167#define nMUX_F(_id, cname, pnames, o, s, w, f, mf) \
168 __MUX(_id, cname, pnames, o, s, w, f, mf)
169
170/**
171 * struct samsung_div_clock - information about div clock
172 * @id: platform specific id of the clock
173 * @name: name of this div clock
174 * @parent_name: name of the parent clock
175 * @flags: optional flags for basic clock
176 * @offset: offset of the register for configuring the div
177 * @shift: starting bit location of the div control bit-field in @reg
178 * @width: width of the bitfield
179 * @div_flags: flags for div-type clock
180 * @table: array of divider/value pairs ending with a div set to 0
181 */
182struct samsung_div_clock {
183 unsigned int id;
184 const char *name;
185 const char *parent_name;
186 unsigned long flags;
187 unsigned long offset;
188 u8 shift;
189 u8 width;
190 u8 div_flags;
191 struct clk_div_table *table;
192};
193
194#define __DIV(_id, cname, pname, o, s, w, f, df, t) \
195 { \
196 .id = _id, \
197 .name = cname, \
198 .parent_name = pname, \
199 .flags = f, \
200 .offset = o, \
201 .shift = s, \
202 .width = w, \
203 .div_flags = df, \
204 .table = t, \
205 }
206
207#define DIV(_id, cname, pname, o, s, w) \
208 __DIV(_id, cname, pname, o, s, w, 0, 0, NULL)
209
210#define DIV_F(_id, cname, pname, o, s, w, f, df) \
211 __DIV(_id, cname, pname, o, s, w, f, df, NULL)
212
213#define DIV_T(_id, cname, pname, o, s, w, t) \
214 __DIV(_id, cname, pname, o, s, w, 0, 0, t)
215
216/**
217 * struct samsung_gate_clock - information about gate clock
218 * @id: platform specific id of the clock
219 * @name: name of this gate clock
220 * @parent_name: name of the parent clock
221 * @flags: optional flags for basic clock
222 * @offset: offset of the register for configuring the gate
223 * @bit_idx: bit index of the gate control bit-field in @reg
224 * @gate_flags: flags for gate-type clock
225 */
226struct samsung_gate_clock {
227 unsigned int id;
228 const char *name;
229 const char *parent_name;
230 unsigned long flags;
231 unsigned long offset;
232 u8 bit_idx;
233 u8 gate_flags;
234};
235
236#define __GATE(_id, cname, pname, o, b, f, gf) \
237 { \
238 .id = _id, \
239 .name = cname, \
240 .parent_name = pname, \
241 .flags = f, \
242 .offset = o, \
243 .bit_idx = b, \
244 .gate_flags = gf, \
245 }
246
247#define GATE(_id, cname, pname, o, b, f, gf) \
248 __GATE(_id, cname, pname, o, b, f, gf)
249
250#define PNAME(x) static const char * const x[] __initconst
251
252/**
253 * struct samsung_clk_reg_dump - register dump of clock controller registers
254 * @offset: clock register offset from the controller base address
255 * @value: the value to be register at offset
256 */
257struct samsung_clk_reg_dump {
258 u32 offset;
259 u32 value;
260};
261
262/**
263 * struct samsung_pll_clock - information about pll clock
264 * @id: platform specific id of the clock
265 * @name: name of this pll clock
266 * @parent_name: name of the parent clock
267 * @flags: optional flags for basic clock
268 * @con_offset: offset of the register for configuring the PLL
269 * @lock_offset: offset of the register for locking the PLL
270 * @type: type of PLL to be registered
271 * @rate_table: array of PLL settings for possible PLL rates
272 */
273struct samsung_pll_clock {
274 unsigned int id;
275 const char *name;
276 const char *parent_name;
277 unsigned long flags;
278 int con_offset;
279 int lock_offset;
280 enum samsung_pll_type type;
281 const struct samsung_pll_rate_table *rate_table;
282};
283
284#define __PLL(_typ, _id, _name, _pname, _flags, _lock, _con, _rtable) \
285 { \
286 .id = _id, \
287 .type = _typ, \
288 .name = _name, \
289 .parent_name = _pname, \
290 .flags = _flags, \
291 .con_offset = _con, \
292 .lock_offset = _lock, \
293 .rate_table = _rtable, \
294 }
295
296#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \
297 __PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock, \
298 _con, _rtable)
299
300struct samsung_cpu_clock {
301 unsigned int id;
302 const char *name;
303 unsigned int parent_id;
304 unsigned int alt_parent_id;
305 unsigned long flags;
306 int offset;
307 enum exynos_cpuclk_layout reg_layout;
308 const struct exynos_cpuclk_cfg_data *cfg;
309};
310
311#define CPU_CLK(_id, _name, _pid, _apid, _flags, _offset, _layout, _cfg) \
312 { \
313 .id = _id, \
314 .name = _name, \
315 .parent_id = _pid, \
316 .alt_parent_id = _apid, \
317 .flags = _flags, \
318 .offset = _offset, \
319 .reg_layout = _layout, \
320 .cfg = _cfg, \
321 }
322
323struct samsung_clock_reg_cache {
324 struct list_head node;
325 void __iomem *reg_base;
326 struct regmap *sysreg;
327 struct samsung_clk_reg_dump *rdump;
328 unsigned int rd_num;
329 const struct samsung_clk_reg_dump *rsuspend;
330 unsigned int rsuspend_num;
331};
332
333/**
334 * struct samsung_cmu_info - all clocks information needed for CMU registration
335 * @pll_clks: list of PLL clocks
336 * @nr_pll_clks: count of clocks in @pll_clks
337 * @mux_clks: list of mux clocks
338 * @nr_mux_clks: count of clocks in @mux_clks
339 * @div_clks: list of div clocks
340 * @nr_div_clks: count of clocks in @div_clks
341 * @gate_clks: list of gate clocks
342 * @nr_gate_clks: count of clocks in @gate_clks
343 * @fixed_clks: list of fixed clocks
344 * @nr_fixed_clks: count clocks in @fixed_clks
345 * @fixed_factor_clks: list of fixed factor clocks
346 * @nr_fixed_factor_clks: count of clocks in @fixed_factor_clks
347 * @nr_clk_ids: total number of clocks with IDs assigned
348 * @cpu_clks: list of CPU clocks
349 * @nr_cpu_clks: count of clocks in @cpu_clks
350 * @clk_regs: list of clock registers
351 * @nr_clk_regs: count of clock registers in @clk_regs
352 * @suspend_regs: list of clock registers to set before suspend
353 * @nr_suspend_regs: count of clock registers in @suspend_regs
354 * @clk_name: name of the parent clock needed for CMU register access
355 * @sysreg_clk_regs: list of sysreg clock registers
356 * @nr_sysreg_clk_regs: count of clock registers in @sysreg_clk_regs
357 * @manual_plls: Enable manual control for PLL clocks
358 * @auto_clock_gate: enable auto clock mode for all components in CMU
359 * @gate_dbg_offset: gate debug reg offset. Used by all gates in auto clk mode
360 * @option_offset: option reg offset. Enables auto clk mode for entire CMU
361 * @drcg_offset: dynamic root clk gate enable register offset in sysreg
362 * @memclk_offset: memclk enable register offset in sysreg
363 */
364struct samsung_cmu_info {
365 const struct samsung_pll_clock *pll_clks;
366 unsigned int nr_pll_clks;
367 const struct samsung_mux_clock *mux_clks;
368 unsigned int nr_mux_clks;
369 const struct samsung_div_clock *div_clks;
370 unsigned int nr_div_clks;
371 const struct samsung_gate_clock *gate_clks;
372 unsigned int nr_gate_clks;
373 const struct samsung_fixed_rate_clock *fixed_clks;
374 unsigned int nr_fixed_clks;
375 const struct samsung_fixed_factor_clock *fixed_factor_clks;
376 unsigned int nr_fixed_factor_clks;
377 unsigned int nr_clk_ids;
378 const struct samsung_cpu_clock *cpu_clks;
379 unsigned int nr_cpu_clks;
380
381 const unsigned long *clk_regs;
382 unsigned int nr_clk_regs;
383
384 const struct samsung_clk_reg_dump *suspend_regs;
385 unsigned int nr_suspend_regs;
386 const char *clk_name;
387
388 const unsigned long *sysreg_clk_regs;
389 unsigned int nr_sysreg_clk_regs;
390
391 /* ARM64 Exynos CMUs */
392 bool manual_plls;
393 bool auto_clock_gate;
394 u32 gate_dbg_offset;
395 u32 option_offset;
396 u32 drcg_offset;
397 u32 memclk_offset;
398};
399
400struct samsung_clk_provider *samsung_clk_init(struct device *dev,
401 void __iomem *base, unsigned long nr_clks);
402void samsung_clk_of_add_provider(struct device_node *np,
403 struct samsung_clk_provider *ctx);
404void samsung_clk_of_register_fixed_ext(
405 struct samsung_clk_provider *ctx,
406 struct samsung_fixed_rate_clock *fixed_rate_clk,
407 unsigned int nr_fixed_rate_clk,
408 const struct of_device_id *clk_matches);
409
410void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
411 struct clk_hw *clk_hw, unsigned int id);
412
413void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
414 const struct samsung_clock_alias *list,
415 unsigned int nr_clk);
416void samsung_clk_register_fixed_rate(
417 struct samsung_clk_provider *ctx,
418 const struct samsung_fixed_rate_clock *clk_list,
419 unsigned int nr_clk);
420void samsung_clk_register_fixed_factor(
421 struct samsung_clk_provider *ctx,
422 const struct samsung_fixed_factor_clock *list,
423 unsigned int nr_clk);
424void samsung_clk_register_mux(struct samsung_clk_provider *ctx,
425 const struct samsung_mux_clock *clk_list,
426 unsigned int nr_clk);
427void samsung_clk_register_div(struct samsung_clk_provider *ctx,
428 const struct samsung_div_clock *clk_list,
429 unsigned int nr_clk);
430void samsung_clk_register_gate(struct samsung_clk_provider *ctx,
431 const struct samsung_gate_clock *clk_list,
432 unsigned int nr_clk);
433void samsung_clk_register_pll(struct samsung_clk_provider *ctx,
434 const struct samsung_pll_clock *pll_list,
435 unsigned int nr_clk);
436void samsung_clk_register_cpu(struct samsung_clk_provider *ctx,
437 const struct samsung_cpu_clock *list, unsigned int nr_clk);
438
439void samsung_cmu_register_clocks(struct samsung_clk_provider *ctx,
440 const struct samsung_cmu_info *cmu,
441 struct device_node *np);
442struct samsung_clk_provider *samsung_cmu_register_one(
443 struct device_node *,
444 const struct samsung_cmu_info *);
445
446#ifdef CONFIG_PM_SLEEP
447void samsung_clk_extended_sleep_init(void __iomem *reg_base,
448 struct regmap *sysreg,
449 const unsigned long *rdump,
450 unsigned long nr_rdump,
451 const struct samsung_clk_reg_dump *rsuspend,
452 unsigned long nr_rsuspend);
453#else
454static inline void samsung_clk_extended_sleep_init(void __iomem *reg_base,
455 struct regmap *sysreg,
456 const unsigned long *rdump,
457 unsigned long nr_rdump,
458 const struct samsung_clk_reg_dump *rsuspend,
459 unsigned long nr_rsuspend) {}
460#endif
461#define samsung_clk_sleep_init(reg_base, sysreg, rdump, nr_rdump) \
462 samsung_clk_extended_sleep_init(reg_base, sysreg, rdump, nr_rdump, \
463 NULL, 0)
464
465void samsung_clk_save(void __iomem *base,
466 struct regmap *regmap,
467 struct samsung_clk_reg_dump *rd,
468 unsigned int num_regs);
469void samsung_clk_restore(void __iomem *base,
470 struct regmap *regmap,
471 const struct samsung_clk_reg_dump *rd,
472 unsigned int num_regs);
473struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
474 const unsigned long *rdump,
475 unsigned long nr_rdump);
476
477void samsung_en_dyn_root_clk_gating(struct device_node *np,
478 struct samsung_clk_provider *ctx,
479 const struct samsung_cmu_info *cmu,
480 bool cmu_has_pm);
481
482struct clk_hw *samsung_register_auto_gate(struct device *dev,
483 struct device_node *np, const char *name,
484 const char *parent_name, const struct clk_hw *parent_hw,
485 const struct clk_parent_data *parent_data,
486 unsigned long flags,
487 void __iomem *reg, u8 bit_idx,
488 u8 clk_gate_flags, spinlock_t *lock);
489
490bool samsung_is_auto_capable(struct device_node *np);
491
492#endif /* __SAMSUNG_CLK_H */