1
2
3
4
5
6#include <linux/stddef.h>
7
8#ifdef CONFIG_CLK_DEBUG
9#undef writel
10#undef readl
11static inline void writel(u32 val, void *addr)
12{
13 printf("Write [0x%p] = 0x%08x\n", addr, val);
14 *(u32 *)addr = val;
15}
16
17static inline u32 readl(void *addr)
18{
19 u32 val = *(u32 *)addr;
20 printf("Read [0x%p] = 0x%08x\n", addr, val);
21 return val;
22}
23#endif
24
25struct clk;
26
27struct clk_lookup {
28 const char *dev_id;
29 const char *con_id;
30 struct clk *clk;
31};
32
33extern struct clk_lookup arch_clk_tbl[];
34extern unsigned int arch_clk_tbl_array_size;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49struct clk_ops {
50 int (*enable) (struct clk *c, int enable);
51 int (*set_rate) (struct clk *c, unsigned long rate);
52 unsigned long (*get_rate) (struct clk *c);
53 unsigned long (*round_rate) (struct clk *c, unsigned long rate);
54 int (*set_parent) (struct clk *c, struct clk *parent);
55};
56
57struct clk {
58 struct clk *parent;
59 const char *name;
60 int use_cnt;
61 unsigned long rate;
62
63
64 unsigned long div;
65
66 struct clk_src *src;
67 struct clk_ops *ops;
68
69 unsigned long ccu_clk_mgr_base;
70 int sel;
71};
72
73struct refclk *refclk_str_to_clk(const char *name);
74
75
76#define PARENT_COUNT_MAX ((u32)U8_MAX)
77
78#define BAD_CLK_INDEX U8_MAX
79#define BAD_CLK_NAME ((const char *)-1)
80
81#define BAD_SCALED_DIV_VALUE U64_MAX
82
83
84
85
86
87#define FLAG(type, flag) BCM_CLK_ ## type ## _FLAGS_ ## flag
88#define FLAG_SET(obj, type, flag) ((obj)->flags |= FLAG(type, flag))
89#define FLAG_CLEAR(obj, type, flag) ((obj)->flags &= ~(FLAG(type, flag)))
90#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag))
91#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag)))
92
93
94
95#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS)
96#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED)
97#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW)
98#define gate_is_sw_controllable(gate) FLAG_TEST(gate, GATE, SW)
99#define gate_is_sw_managed(gate) FLAG_TEST(gate, GATE, SW_MANAGED)
100#define gate_is_no_disable(gate) FLAG_TEST(gate, GATE, NO_DISABLE)
101
102#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED)
103
104#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS)
105#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED)
106#define divider_has_fraction(div) (!divider_is_fixed(div) && \
107 (div)->frac_width > 0)
108
109#define selector_exists(sel) ((sel)->width != 0)
110#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS)
111
112
113enum bcm_clk_type {
114 bcm_clk_none,
115 bcm_clk_bus,
116 bcm_clk_core,
117 bcm_clk_peri
118};
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144struct bcm_clk_gate {
145 u32 offset;
146 u32 status_bit;
147 u32 en_bit;
148 u32 hw_sw_sel_bit;
149 u32 flags;
150};
151
152
153
154
155
156
157
158
159
160#define BCM_CLK_GATE_FLAGS_EXISTS ((u32)1 << 0)
161#define BCM_CLK_GATE_FLAGS_HW ((u32)1 << 1)
162#define BCM_CLK_GATE_FLAGS_SW ((u32)1 << 2)
163#define BCM_CLK_GATE_FLAGS_NO_DISABLE ((u32)1 << 3)
164#define BCM_CLK_GATE_FLAGS_SW_MANAGED ((u32)1 << 4)
165#define BCM_CLK_GATE_FLAGS_ENABLED ((u32)1 << 5)
166
167
168
169
170
171
172
173
174#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
175 { \
176 .offset = (_offset), \
177 .status_bit = (_status_bit), \
178 .en_bit = (_en_bit), \
179 .hw_sw_sel_bit = (_hw_sw_sel_bit), \
180 .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \
181 FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)| \
182 FLAG(GATE, EXISTS), \
183 }
184
185
186#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
187 { \
188 .offset = (_offset), \
189 .status_bit = (_status_bit), \
190 .en_bit = (_en_bit), \
191 .hw_sw_sel_bit = (_hw_sw_sel_bit), \
192 .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \
193 FLAG(GATE, EXISTS), \
194 }
195
196
197#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
198 { \
199 .offset = (_offset), \
200 .status_bit = (_status_bit), \
201 .en_bit = (_en_bit), \
202 .hw_sw_sel_bit = (_hw_sw_sel_bit), \
203 .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \
204 FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS), \
205 }
206
207
208#define SW_ONLY_GATE(_offset, _status_bit, _en_bit) \
209 { \
210 .offset = (_offset), \
211 .status_bit = (_status_bit), \
212 .en_bit = (_en_bit), \
213 .flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)| \
214 FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS), \
215 }
216
217
218#define HW_ONLY_GATE(_offset, _status_bit) \
219 { \
220 .offset = (_offset), \
221 .status_bit = (_status_bit), \
222 .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265struct bcm_clk_div {
266 union {
267 struct {
268 u32 offset;
269 u32 shift;
270 u32 width;
271 u32 frac_width;
272
273 u64 scaled_div;
274 };
275 u32 fixed;
276 };
277 u32 flags;
278};
279
280
281
282
283
284
285#define BCM_CLK_DIV_FLAGS_EXISTS ((u32)1 << 0)
286#define BCM_CLK_DIV_FLAGS_FIXED ((u32)1 << 1)
287
288
289
290
291#define FIXED_DIVIDER(_value) \
292 { \
293 .fixed = (_value), \
294 .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \
295 }
296
297
298#define DIVIDER(_offset, _shift, _width) \
299 { \
300 .offset = (_offset), \
301 .shift = (_shift), \
302 .width = (_width), \
303 .scaled_div = BAD_SCALED_DIV_VALUE, \
304 .flags = FLAG(DIV, EXISTS), \
305 }
306
307
308#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \
309 { \
310 .offset = (_offset), \
311 .shift = (_shift), \
312 .width = (_width), \
313 .frac_width = (_frac_width), \
314 .scaled_div = BAD_SCALED_DIV_VALUE, \
315 .flags = FLAG(DIV, EXISTS), \
316 }
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338struct bcm_clk_sel {
339 u32 offset;
340 u32 shift;
341 u32 width;
342
343 u32 parent_count;
344 u32 *parent_sel;
345 u8 clk_index;
346};
347
348
349#define SELECTOR(_offset, _shift, _width) \
350 { \
351 .offset = (_offset), \
352 .shift = (_shift), \
353 .width = (_width), \
354 .clk_index = BAD_CLK_INDEX, \
355 }
356
357
358
359
360
361
362
363
364
365
366
367
368
369struct bcm_clk_trig {
370 u32 offset;
371 u32 bit;
372 u32 flags;
373};
374
375
376
377
378
379#define BCM_CLK_TRIG_FLAGS_EXISTS ((u32)1 << 0)
380
381
382#define TRIGGER(_offset, _bit) \
383 { \
384 .offset = (_offset), \
385 .bit = (_bit), \
386 .flags = FLAG(TRIG, EXISTS), \
387 }
388
389struct bus_clk_data {
390 struct bcm_clk_gate gate;
391};
392
393struct core_clk_data {
394 struct bcm_clk_gate gate;
395};
396
397struct peri_clk_data {
398 struct bcm_clk_gate gate;
399 struct bcm_clk_trig pre_trig;
400 struct bcm_clk_div pre_div;
401 struct bcm_clk_trig trig;
402 struct bcm_clk_div div;
403 struct bcm_clk_sel sel;
404 const char *clocks[];
405};
406#define CLOCKS(...) { __VA_ARGS__, NULL, }
407#define NO_CLOCKS { NULL, }
408
409struct refclk {
410 struct clk clk;
411};
412
413struct peri_clock {
414 struct clk clk;
415 struct peri_clk_data *data;
416};
417
418struct ccu_clock {
419 struct clk clk;
420
421 int num_policy_masks;
422 unsigned long policy_freq_offset;
423 int freq_bit_shift;
424 unsigned long policy_ctl_offset;
425 unsigned long policy0_mask_offset;
426 unsigned long policy1_mask_offset;
427 unsigned long policy2_mask_offset;
428 unsigned long policy3_mask_offset;
429 unsigned long policy0_mask2_offset;
430 unsigned long policy1_mask2_offset;
431 unsigned long policy2_mask2_offset;
432 unsigned long policy3_mask2_offset;
433 unsigned long lvm_en_offset;
434
435 int freq_id;
436 unsigned long *freq_tbl;
437};
438
439struct bus_clock {
440 struct clk clk;
441 struct bus_clk_data *data;
442 unsigned long *freq_tbl;
443};
444
445struct ref_clock {
446 struct clk clk;
447};
448
449static inline int is_same_clock(struct clk *a, struct clk *b)
450{
451 return (a == b);
452}
453
454#define to_clk(p) (&((p)->clk))
455#define name_to_clk(name) (&((name##_clk).clk))
456
457#define CLK_LK(name) \
458{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),}
459
460static inline struct refclk *to_refclk(struct clk *clock)
461{
462 return container_of(clock, struct refclk, clk);
463}
464
465static inline struct peri_clock *to_peri_clk(struct clk *clock)
466{
467 return container_of(clock, struct peri_clock, clk);
468}
469
470static inline struct ccu_clock *to_ccu_clk(struct clk *clock)
471{
472 return container_of(clock, struct ccu_clock, clk);
473}
474
475static inline struct bus_clock *to_bus_clk(struct clk *clock)
476{
477 return container_of(clock, struct bus_clock, clk);
478}
479
480static inline struct ref_clock *to_ref_clk(struct clk *clock)
481{
482 return container_of(clock, struct ref_clock, clk);
483}
484
485extern struct clk_ops peri_clk_ops;
486extern struct clk_ops ccu_clk_ops;
487extern struct clk_ops bus_clk_ops;
488extern struct clk_ops ref_clk_ops;
489
490extern int clk_get_and_enable(char *clkstr);
491