Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/jz4740/clock.c
10817 views
1
/*
2
* Copyright (C) 2010, Lars-Peter Clausen <[email protected]>
3
* JZ4740 SoC clock support
4
*
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License as published by the
7
* Free Software Foundation; either version 2 of the License, or (at your
8
* option) any later version.
9
*
10
* You should have received a copy of the GNU General Public License along
11
* with this program; if not, write to the Free Software Foundation, Inc.,
12
* 675 Mass Ave, Cambridge, MA 02139, USA.
13
*
14
*/
15
16
#include <linux/kernel.h>
17
#include <linux/errno.h>
18
#include <linux/clk.h>
19
#include <linux/spinlock.h>
20
#include <linux/io.h>
21
#include <linux/module.h>
22
#include <linux/list.h>
23
#include <linux/err.h>
24
25
#include <asm/mach-jz4740/clock.h>
26
#include <asm/mach-jz4740/base.h>
27
28
#include "clock.h"
29
30
#define JZ_REG_CLOCK_CTRL 0x00
31
#define JZ_REG_CLOCK_LOW_POWER 0x04
32
#define JZ_REG_CLOCK_PLL 0x10
33
#define JZ_REG_CLOCK_GATE 0x20
34
#define JZ_REG_CLOCK_SLEEP_CTRL 0x24
35
#define JZ_REG_CLOCK_I2S 0x60
36
#define JZ_REG_CLOCK_LCD 0x64
37
#define JZ_REG_CLOCK_MMC 0x68
38
#define JZ_REG_CLOCK_UHC 0x6C
39
#define JZ_REG_CLOCK_SPI 0x74
40
41
#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
42
#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
43
#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
44
#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
45
#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
46
#define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
47
#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
48
#define JZ_CLOCK_CTRL_UDIV_OFFSET 23
49
#define JZ_CLOCK_CTRL_LDIV_OFFSET 16
50
#define JZ_CLOCK_CTRL_MDIV_OFFSET 12
51
#define JZ_CLOCK_CTRL_PDIV_OFFSET 8
52
#define JZ_CLOCK_CTRL_HDIV_OFFSET 4
53
#define JZ_CLOCK_CTRL_CDIV_OFFSET 0
54
55
#define JZ_CLOCK_GATE_UART0 BIT(0)
56
#define JZ_CLOCK_GATE_TCU BIT(1)
57
#define JZ_CLOCK_GATE_RTC BIT(2)
58
#define JZ_CLOCK_GATE_I2C BIT(3)
59
#define JZ_CLOCK_GATE_SPI BIT(4)
60
#define JZ_CLOCK_GATE_AIC BIT(5)
61
#define JZ_CLOCK_GATE_I2S BIT(6)
62
#define JZ_CLOCK_GATE_MMC BIT(7)
63
#define JZ_CLOCK_GATE_ADC BIT(8)
64
#define JZ_CLOCK_GATE_CIM BIT(9)
65
#define JZ_CLOCK_GATE_LCD BIT(10)
66
#define JZ_CLOCK_GATE_UDC BIT(11)
67
#define JZ_CLOCK_GATE_DMAC BIT(12)
68
#define JZ_CLOCK_GATE_IPU BIT(13)
69
#define JZ_CLOCK_GATE_UHC BIT(14)
70
#define JZ_CLOCK_GATE_UART1 BIT(15)
71
72
#define JZ_CLOCK_I2S_DIV_MASK 0x01ff
73
74
#define JZ_CLOCK_LCD_DIV_MASK 0x01ff
75
76
#define JZ_CLOCK_MMC_DIV_MASK 0x001f
77
78
#define JZ_CLOCK_UHC_DIV_MASK 0x000f
79
80
#define JZ_CLOCK_SPI_SRC_PLL BIT(31)
81
#define JZ_CLOCK_SPI_DIV_MASK 0x000f
82
83
#define JZ_CLOCK_PLL_M_MASK 0x01ff
84
#define JZ_CLOCK_PLL_N_MASK 0x001f
85
#define JZ_CLOCK_PLL_OD_MASK 0x0003
86
#define JZ_CLOCK_PLL_STABLE BIT(10)
87
#define JZ_CLOCK_PLL_BYPASS BIT(9)
88
#define JZ_CLOCK_PLL_ENABLED BIT(8)
89
#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f
90
#define JZ_CLOCK_PLL_M_OFFSET 23
91
#define JZ_CLOCK_PLL_N_OFFSET 18
92
#define JZ_CLOCK_PLL_OD_OFFSET 16
93
94
#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
95
#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
96
97
#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
98
#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
99
100
static void __iomem *jz_clock_base;
101
static spinlock_t jz_clock_lock;
102
static LIST_HEAD(jz_clocks);
103
104
struct main_clk {
105
struct clk clk;
106
uint32_t div_offset;
107
};
108
109
struct divided_clk {
110
struct clk clk;
111
uint32_t reg;
112
uint32_t mask;
113
};
114
115
struct static_clk {
116
struct clk clk;
117
unsigned long rate;
118
};
119
120
static uint32_t jz_clk_reg_read(int reg)
121
{
122
return readl(jz_clock_base + reg);
123
}
124
125
static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
126
{
127
uint32_t val2;
128
129
spin_lock(&jz_clock_lock);
130
val2 = readl(jz_clock_base + reg);
131
val2 &= ~mask;
132
val2 |= val;
133
writel(val2, jz_clock_base + reg);
134
spin_unlock(&jz_clock_lock);
135
}
136
137
static void jz_clk_reg_set_bits(int reg, uint32_t mask)
138
{
139
uint32_t val;
140
141
spin_lock(&jz_clock_lock);
142
val = readl(jz_clock_base + reg);
143
val |= mask;
144
writel(val, jz_clock_base + reg);
145
spin_unlock(&jz_clock_lock);
146
}
147
148
static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
149
{
150
uint32_t val;
151
152
spin_lock(&jz_clock_lock);
153
val = readl(jz_clock_base + reg);
154
val &= ~mask;
155
writel(val, jz_clock_base + reg);
156
spin_unlock(&jz_clock_lock);
157
}
158
159
static int jz_clk_enable_gating(struct clk *clk)
160
{
161
if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
162
return -EINVAL;
163
164
jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
165
return 0;
166
}
167
168
static int jz_clk_disable_gating(struct clk *clk)
169
{
170
if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
171
return -EINVAL;
172
173
jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
174
return 0;
175
}
176
177
static int jz_clk_is_enabled_gating(struct clk *clk)
178
{
179
if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
180
return 1;
181
182
return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
183
}
184
185
static unsigned long jz_clk_static_get_rate(struct clk *clk)
186
{
187
return ((struct static_clk *)clk)->rate;
188
}
189
190
static int jz_clk_ko_enable(struct clk *clk)
191
{
192
jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
193
return 0;
194
}
195
196
static int jz_clk_ko_disable(struct clk *clk)
197
{
198
jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
199
return 0;
200
}
201
202
static int jz_clk_ko_is_enabled(struct clk *clk)
203
{
204
return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
205
}
206
207
static const int pllno[] = {1, 2, 2, 4};
208
209
static unsigned long jz_clk_pll_get_rate(struct clk *clk)
210
{
211
uint32_t val;
212
int m;
213
int n;
214
int od;
215
216
val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
217
218
if (val & JZ_CLOCK_PLL_BYPASS)
219
return clk_get_rate(clk->parent);
220
221
m = ((val >> 23) & 0x1ff) + 2;
222
n = ((val >> 18) & 0x1f) + 2;
223
od = (val >> 16) & 0x3;
224
225
return ((clk_get_rate(clk->parent) / n) * m) / pllno[od];
226
}
227
228
static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
229
{
230
uint32_t reg;
231
232
reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
233
if (reg & JZ_CLOCK_CTRL_PLL_HALF)
234
return jz_clk_pll_get_rate(clk->parent);
235
return jz_clk_pll_get_rate(clk->parent) >> 1;
236
}
237
238
static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
239
240
static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
241
{
242
unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
243
int div;
244
245
div = parent_rate / rate;
246
if (div > 32)
247
return parent_rate / 32;
248
else if (div < 1)
249
return parent_rate;
250
251
div &= (0x3 << (ffs(div) - 1));
252
253
return parent_rate / div;
254
}
255
256
static unsigned long jz_clk_main_get_rate(struct clk *clk)
257
{
258
struct main_clk *mclk = (struct main_clk *)clk;
259
uint32_t div;
260
261
div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
262
263
div >>= mclk->div_offset;
264
div &= 0xf;
265
266
if (div >= ARRAY_SIZE(jz_clk_main_divs))
267
div = ARRAY_SIZE(jz_clk_main_divs) - 1;
268
269
return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
270
}
271
272
static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
273
{
274
struct main_clk *mclk = (struct main_clk *)clk;
275
int i;
276
int div;
277
unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
278
279
rate = jz_clk_main_round_rate(clk, rate);
280
281
div = parent_rate / rate;
282
283
i = (ffs(div) - 1) << 1;
284
if (i > 0 && !(div & BIT(i-1)))
285
i -= 1;
286
287
jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
288
0xf << mclk->div_offset);
289
290
return 0;
291
}
292
293
static struct clk_ops jz_clk_static_ops = {
294
.get_rate = jz_clk_static_get_rate,
295
.enable = jz_clk_enable_gating,
296
.disable = jz_clk_disable_gating,
297
.is_enabled = jz_clk_is_enabled_gating,
298
};
299
300
static struct static_clk jz_clk_ext = {
301
.clk = {
302
.name = "ext",
303
.gate_bit = JZ4740_CLK_NOT_GATED,
304
.ops = &jz_clk_static_ops,
305
},
306
};
307
308
static struct clk_ops jz_clk_pll_ops = {
309
.get_rate = jz_clk_pll_get_rate,
310
};
311
312
static struct clk jz_clk_pll = {
313
.name = "pll",
314
.parent = &jz_clk_ext.clk,
315
.ops = &jz_clk_pll_ops,
316
};
317
318
static struct clk_ops jz_clk_pll_half_ops = {
319
.get_rate = jz_clk_pll_half_get_rate,
320
};
321
322
static struct clk jz_clk_pll_half = {
323
.name = "pll half",
324
.parent = &jz_clk_pll,
325
.ops = &jz_clk_pll_half_ops,
326
};
327
328
static const struct clk_ops jz_clk_main_ops = {
329
.get_rate = jz_clk_main_get_rate,
330
.set_rate = jz_clk_main_set_rate,
331
.round_rate = jz_clk_main_round_rate,
332
};
333
334
static struct main_clk jz_clk_cpu = {
335
.clk = {
336
.name = "cclk",
337
.parent = &jz_clk_pll,
338
.ops = &jz_clk_main_ops,
339
},
340
.div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
341
};
342
343
static struct main_clk jz_clk_memory = {
344
.clk = {
345
.name = "mclk",
346
.parent = &jz_clk_pll,
347
.ops = &jz_clk_main_ops,
348
},
349
.div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
350
};
351
352
static struct main_clk jz_clk_high_speed_peripheral = {
353
.clk = {
354
.name = "hclk",
355
.parent = &jz_clk_pll,
356
.ops = &jz_clk_main_ops,
357
},
358
.div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
359
};
360
361
362
static struct main_clk jz_clk_low_speed_peripheral = {
363
.clk = {
364
.name = "pclk",
365
.parent = &jz_clk_pll,
366
.ops = &jz_clk_main_ops,
367
},
368
.div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
369
};
370
371
static const struct clk_ops jz_clk_ko_ops = {
372
.enable = jz_clk_ko_enable,
373
.disable = jz_clk_ko_disable,
374
.is_enabled = jz_clk_ko_is_enabled,
375
};
376
377
static struct clk jz_clk_ko = {
378
.name = "cko",
379
.parent = &jz_clk_memory.clk,
380
.ops = &jz_clk_ko_ops,
381
};
382
383
static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
384
{
385
if (parent == &jz_clk_pll)
386
jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
387
else if (parent == &jz_clk_ext.clk)
388
jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
389
else
390
return -EINVAL;
391
392
clk->parent = parent;
393
394
return 0;
395
}
396
397
static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
398
{
399
if (parent == &jz_clk_pll_half)
400
jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
401
else if (parent == &jz_clk_ext.clk)
402
jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
403
else
404
return -EINVAL;
405
406
clk->parent = parent;
407
408
return 0;
409
}
410
411
static int jz_clk_udc_enable(struct clk *clk)
412
{
413
jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
414
JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
415
416
return 0;
417
}
418
419
static int jz_clk_udc_disable(struct clk *clk)
420
{
421
jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
422
JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
423
424
return 0;
425
}
426
427
static int jz_clk_udc_is_enabled(struct clk *clk)
428
{
429
return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
430
JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
431
}
432
433
static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
434
{
435
if (parent == &jz_clk_pll_half)
436
jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
437
else if (parent == &jz_clk_ext.clk)
438
jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
439
else
440
return -EINVAL;
441
442
clk->parent = parent;
443
444
return 0;
445
}
446
447
static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
448
{
449
int div;
450
451
if (clk->parent == &jz_clk_ext.clk)
452
return -EINVAL;
453
454
div = clk_get_rate(clk->parent) / rate - 1;
455
456
if (div < 0)
457
div = 0;
458
else if (div > 63)
459
div = 63;
460
461
jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
462
JZ_CLOCK_CTRL_UDIV_MASK);
463
return 0;
464
}
465
466
static unsigned long jz_clk_udc_get_rate(struct clk *clk)
467
{
468
int div;
469
470
if (clk->parent == &jz_clk_ext.clk)
471
return clk_get_rate(clk->parent);
472
473
div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
474
div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
475
div += 1;
476
477
return clk_get_rate(clk->parent) / div;
478
}
479
480
static unsigned long jz_clk_divided_get_rate(struct clk *clk)
481
{
482
struct divided_clk *dclk = (struct divided_clk *)clk;
483
int div;
484
485
if (clk->parent == &jz_clk_ext.clk)
486
return clk_get_rate(clk->parent);
487
488
div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
489
490
return clk_get_rate(clk->parent) / div;
491
}
492
493
static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
494
{
495
struct divided_clk *dclk = (struct divided_clk *)clk;
496
int div;
497
498
if (clk->parent == &jz_clk_ext.clk)
499
return -EINVAL;
500
501
div = clk_get_rate(clk->parent) / rate - 1;
502
503
if (div < 0)
504
div = 0;
505
else if (div > dclk->mask)
506
div = dclk->mask;
507
508
jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
509
510
return 0;
511
}
512
513
static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
514
{
515
int div;
516
unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
517
518
if (rate > 150000000)
519
return 150000000;
520
521
div = parent_rate / rate;
522
if (div < 1)
523
div = 1;
524
else if (div > 32)
525
div = 32;
526
527
return parent_rate / div;
528
}
529
530
static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
531
{
532
int div;
533
534
if (rate > 150000000)
535
return -EINVAL;
536
537
div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
538
if (div < 0)
539
div = 0;
540
else if (div > 31)
541
div = 31;
542
543
jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
544
JZ_CLOCK_CTRL_LDIV_MASK);
545
546
return 0;
547
}
548
549
static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
550
{
551
int div;
552
553
div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
554
div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
555
556
return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
557
}
558
559
static const struct clk_ops jz_clk_ops_ld = {
560
.set_rate = jz_clk_ldclk_set_rate,
561
.get_rate = jz_clk_ldclk_get_rate,
562
.round_rate = jz_clk_ldclk_round_rate,
563
.enable = jz_clk_enable_gating,
564
.disable = jz_clk_disable_gating,
565
.is_enabled = jz_clk_is_enabled_gating,
566
};
567
568
static struct clk jz_clk_ld = {
569
.name = "lcd",
570
.gate_bit = JZ_CLOCK_GATE_LCD,
571
.parent = &jz_clk_pll_half,
572
.ops = &jz_clk_ops_ld,
573
};
574
575
static const struct clk_ops jz_clk_i2s_ops = {
576
.set_rate = jz_clk_divided_set_rate,
577
.get_rate = jz_clk_divided_get_rate,
578
.enable = jz_clk_enable_gating,
579
.disable = jz_clk_disable_gating,
580
.is_enabled = jz_clk_is_enabled_gating,
581
.set_parent = jz_clk_i2s_set_parent,
582
};
583
584
static const struct clk_ops jz_clk_spi_ops = {
585
.set_rate = jz_clk_divided_set_rate,
586
.get_rate = jz_clk_divided_get_rate,
587
.enable = jz_clk_enable_gating,
588
.disable = jz_clk_disable_gating,
589
.is_enabled = jz_clk_is_enabled_gating,
590
.set_parent = jz_clk_spi_set_parent,
591
};
592
593
static const struct clk_ops jz_clk_divided_ops = {
594
.set_rate = jz_clk_divided_set_rate,
595
.get_rate = jz_clk_divided_get_rate,
596
.enable = jz_clk_enable_gating,
597
.disable = jz_clk_disable_gating,
598
.is_enabled = jz_clk_is_enabled_gating,
599
};
600
601
static struct divided_clk jz4740_clock_divided_clks[] = {
602
[0] = {
603
.clk = {
604
.name = "i2s",
605
.parent = &jz_clk_ext.clk,
606
.gate_bit = JZ_CLOCK_GATE_I2S,
607
.ops = &jz_clk_i2s_ops,
608
},
609
.reg = JZ_REG_CLOCK_I2S,
610
.mask = JZ_CLOCK_I2S_DIV_MASK,
611
},
612
[1] = {
613
.clk = {
614
.name = "spi",
615
.parent = &jz_clk_ext.clk,
616
.gate_bit = JZ_CLOCK_GATE_SPI,
617
.ops = &jz_clk_spi_ops,
618
},
619
.reg = JZ_REG_CLOCK_SPI,
620
.mask = JZ_CLOCK_SPI_DIV_MASK,
621
},
622
[2] = {
623
.clk = {
624
.name = "lcd_pclk",
625
.parent = &jz_clk_pll_half,
626
.gate_bit = JZ4740_CLK_NOT_GATED,
627
.ops = &jz_clk_divided_ops,
628
},
629
.reg = JZ_REG_CLOCK_LCD,
630
.mask = JZ_CLOCK_LCD_DIV_MASK,
631
},
632
[3] = {
633
.clk = {
634
.name = "mmc",
635
.parent = &jz_clk_pll_half,
636
.gate_bit = JZ_CLOCK_GATE_MMC,
637
.ops = &jz_clk_divided_ops,
638
},
639
.reg = JZ_REG_CLOCK_MMC,
640
.mask = JZ_CLOCK_MMC_DIV_MASK,
641
},
642
[4] = {
643
.clk = {
644
.name = "uhc",
645
.parent = &jz_clk_pll_half,
646
.gate_bit = JZ_CLOCK_GATE_UHC,
647
.ops = &jz_clk_divided_ops,
648
},
649
.reg = JZ_REG_CLOCK_UHC,
650
.mask = JZ_CLOCK_UHC_DIV_MASK,
651
},
652
};
653
654
static const struct clk_ops jz_clk_udc_ops = {
655
.set_parent = jz_clk_udc_set_parent,
656
.set_rate = jz_clk_udc_set_rate,
657
.get_rate = jz_clk_udc_get_rate,
658
.enable = jz_clk_udc_enable,
659
.disable = jz_clk_udc_disable,
660
.is_enabled = jz_clk_udc_is_enabled,
661
};
662
663
static const struct clk_ops jz_clk_simple_ops = {
664
.enable = jz_clk_enable_gating,
665
.disable = jz_clk_disable_gating,
666
.is_enabled = jz_clk_is_enabled_gating,
667
};
668
669
static struct clk jz4740_clock_simple_clks[] = {
670
[0] = {
671
.name = "udc",
672
.parent = &jz_clk_ext.clk,
673
.ops = &jz_clk_udc_ops,
674
},
675
[1] = {
676
.name = "uart0",
677
.parent = &jz_clk_ext.clk,
678
.gate_bit = JZ_CLOCK_GATE_UART0,
679
.ops = &jz_clk_simple_ops,
680
},
681
[2] = {
682
.name = "uart1",
683
.parent = &jz_clk_ext.clk,
684
.gate_bit = JZ_CLOCK_GATE_UART1,
685
.ops = &jz_clk_simple_ops,
686
},
687
[3] = {
688
.name = "dma",
689
.parent = &jz_clk_high_speed_peripheral.clk,
690
.gate_bit = JZ_CLOCK_GATE_UART0,
691
.ops = &jz_clk_simple_ops,
692
},
693
[4] = {
694
.name = "ipu",
695
.parent = &jz_clk_high_speed_peripheral.clk,
696
.gate_bit = JZ_CLOCK_GATE_IPU,
697
.ops = &jz_clk_simple_ops,
698
},
699
[5] = {
700
.name = "adc",
701
.parent = &jz_clk_ext.clk,
702
.gate_bit = JZ_CLOCK_GATE_ADC,
703
.ops = &jz_clk_simple_ops,
704
},
705
[6] = {
706
.name = "i2c",
707
.parent = &jz_clk_ext.clk,
708
.gate_bit = JZ_CLOCK_GATE_I2C,
709
.ops = &jz_clk_simple_ops,
710
},
711
[7] = {
712
.name = "aic",
713
.parent = &jz_clk_ext.clk,
714
.gate_bit = JZ_CLOCK_GATE_AIC,
715
.ops = &jz_clk_simple_ops,
716
},
717
};
718
719
static struct static_clk jz_clk_rtc = {
720
.clk = {
721
.name = "rtc",
722
.gate_bit = JZ_CLOCK_GATE_RTC,
723
.ops = &jz_clk_static_ops,
724
},
725
.rate = 32768,
726
};
727
728
int clk_enable(struct clk *clk)
729
{
730
if (!clk->ops->enable)
731
return -EINVAL;
732
733
return clk->ops->enable(clk);
734
}
735
EXPORT_SYMBOL_GPL(clk_enable);
736
737
void clk_disable(struct clk *clk)
738
{
739
if (clk->ops->disable)
740
clk->ops->disable(clk);
741
}
742
EXPORT_SYMBOL_GPL(clk_disable);
743
744
int clk_is_enabled(struct clk *clk)
745
{
746
if (clk->ops->is_enabled)
747
return clk->ops->is_enabled(clk);
748
749
return 1;
750
}
751
752
unsigned long clk_get_rate(struct clk *clk)
753
{
754
if (clk->ops->get_rate)
755
return clk->ops->get_rate(clk);
756
if (clk->parent)
757
return clk_get_rate(clk->parent);
758
759
return -EINVAL;
760
}
761
EXPORT_SYMBOL_GPL(clk_get_rate);
762
763
int clk_set_rate(struct clk *clk, unsigned long rate)
764
{
765
if (!clk->ops->set_rate)
766
return -EINVAL;
767
return clk->ops->set_rate(clk, rate);
768
}
769
EXPORT_SYMBOL_GPL(clk_set_rate);
770
771
long clk_round_rate(struct clk *clk, unsigned long rate)
772
{
773
if (clk->ops->round_rate)
774
return clk->ops->round_rate(clk, rate);
775
776
return -EINVAL;
777
}
778
EXPORT_SYMBOL_GPL(clk_round_rate);
779
780
int clk_set_parent(struct clk *clk, struct clk *parent)
781
{
782
int ret;
783
int enabled;
784
785
if (!clk->ops->set_parent)
786
return -EINVAL;
787
788
enabled = clk_is_enabled(clk);
789
if (enabled)
790
clk_disable(clk);
791
ret = clk->ops->set_parent(clk, parent);
792
if (enabled)
793
clk_enable(clk);
794
795
jz4740_clock_debugfs_update_parent(clk);
796
797
return ret;
798
}
799
EXPORT_SYMBOL_GPL(clk_set_parent);
800
801
struct clk *clk_get(struct device *dev, const char *name)
802
{
803
struct clk *clk;
804
805
list_for_each_entry(clk, &jz_clocks, list) {
806
if (strcmp(clk->name, name) == 0)
807
return clk;
808
}
809
return ERR_PTR(-ENXIO);
810
}
811
EXPORT_SYMBOL_GPL(clk_get);
812
813
void clk_put(struct clk *clk)
814
{
815
}
816
EXPORT_SYMBOL_GPL(clk_put);
817
818
static inline void clk_add(struct clk *clk)
819
{
820
list_add_tail(&clk->list, &jz_clocks);
821
822
jz4740_clock_debugfs_add_clk(clk);
823
}
824
825
static void clk_register_clks(void)
826
{
827
size_t i;
828
829
clk_add(&jz_clk_ext.clk);
830
clk_add(&jz_clk_pll);
831
clk_add(&jz_clk_pll_half);
832
clk_add(&jz_clk_cpu.clk);
833
clk_add(&jz_clk_high_speed_peripheral.clk);
834
clk_add(&jz_clk_low_speed_peripheral.clk);
835
clk_add(&jz_clk_ko);
836
clk_add(&jz_clk_ld);
837
clk_add(&jz_clk_rtc.clk);
838
839
for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
840
clk_add(&jz4740_clock_divided_clks[i].clk);
841
842
for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
843
clk_add(&jz4740_clock_simple_clks[i]);
844
}
845
846
void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
847
{
848
switch (mode) {
849
case JZ4740_WAIT_MODE_IDLE:
850
jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
851
break;
852
case JZ4740_WAIT_MODE_SLEEP:
853
jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
854
break;
855
}
856
}
857
858
void jz4740_clock_udc_disable_auto_suspend(void)
859
{
860
jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
861
}
862
EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
863
864
void jz4740_clock_udc_enable_auto_suspend(void)
865
{
866
jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
867
}
868
EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
869
870
void jz4740_clock_suspend(void)
871
{
872
jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
873
JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
874
875
jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
876
}
877
878
void jz4740_clock_resume(void)
879
{
880
uint32_t pll;
881
882
jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
883
884
do {
885
pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
886
} while (!(pll & JZ_CLOCK_PLL_STABLE));
887
888
jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
889
JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
890
}
891
892
static int jz4740_clock_init(void)
893
{
894
uint32_t val;
895
896
jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
897
if (!jz_clock_base)
898
return -EBUSY;
899
900
spin_lock_init(&jz_clock_lock);
901
902
jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
903
jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
904
905
val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
906
907
if (val & JZ_CLOCK_SPI_SRC_PLL)
908
jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
909
910
val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
911
912
if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
913
jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
914
915
if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
916
jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
917
918
jz4740_clock_debugfs_init();
919
920
clk_register_clks();
921
922
return 0;
923
}
924
arch_initcall(jz4740_clock_init);
925
926