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