2 * Copyright 2014 Linaro Ltd.
3 * Copyright (C) 2014 ZTE Corporation.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/clk-provider.h>
11 #include <linux/err.h>
13 #include <linux/iopoll.h>
14 #include <linux/slab.h>
15 #include <linux/spinlock.h>
16 #include <asm/div64.h>
20 #define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
21 #define to_clk_zx_audio(_hw) container_of(_hw, struct clk_zx_audio, hw)
23 #define CFG0_CFG1_OFFSET 4
24 #define LOCK_FLAG BIT(30)
25 #define POWER_DOWN BIT(31)
27 static int rate_to_idx(struct clk_zx_pll
*zx_pll
, unsigned long rate
)
29 const struct zx_pll_config
*config
= zx_pll
->lookup_table
;
32 for (i
= 0; i
< zx_pll
->count
; i
++) {
33 if (config
[i
].rate
> rate
)
34 return i
> 0 ? i
- 1 : 0;
36 if (config
[i
].rate
== rate
)
43 static int hw_to_idx(struct clk_zx_pll
*zx_pll
)
45 const struct zx_pll_config
*config
= zx_pll
->lookup_table
;
49 hw_cfg0
= readl_relaxed(zx_pll
->reg_base
);
50 hw_cfg1
= readl_relaxed(zx_pll
->reg_base
+ CFG0_CFG1_OFFSET
);
52 /* For matching the value in lookup table */
53 hw_cfg0
&= ~LOCK_FLAG
;
54 hw_cfg0
|= POWER_DOWN
;
56 for (i
= 0; i
< zx_pll
->count
; i
++) {
57 if (hw_cfg0
== config
[i
].cfg0
&& hw_cfg1
== config
[i
].cfg1
)
64 static unsigned long zx_pll_recalc_rate(struct clk_hw
*hw
,
65 unsigned long parent_rate
)
67 struct clk_zx_pll
*zx_pll
= to_clk_zx_pll(hw
);
70 idx
= hw_to_idx(zx_pll
);
71 if (unlikely(idx
== -EINVAL
))
74 return zx_pll
->lookup_table
[idx
].rate
;
77 static long zx_pll_round_rate(struct clk_hw
*hw
, unsigned long rate
,
80 struct clk_zx_pll
*zx_pll
= to_clk_zx_pll(hw
);
83 idx
= rate_to_idx(zx_pll
, rate
);
85 return zx_pll
->lookup_table
[idx
].rate
;
88 static int zx_pll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
89 unsigned long parent_rate
)
91 /* Assume current cpu is not running on current PLL */
92 struct clk_zx_pll
*zx_pll
= to_clk_zx_pll(hw
);
93 const struct zx_pll_config
*config
;
96 idx
= rate_to_idx(zx_pll
, rate
);
97 config
= &zx_pll
->lookup_table
[idx
];
99 writel_relaxed(config
->cfg0
, zx_pll
->reg_base
);
100 writel_relaxed(config
->cfg1
, zx_pll
->reg_base
+ CFG0_CFG1_OFFSET
);
105 static int zx_pll_enable(struct clk_hw
*hw
)
107 struct clk_zx_pll
*zx_pll
= to_clk_zx_pll(hw
);
110 reg
= readl_relaxed(zx_pll
->reg_base
);
111 writel_relaxed(reg
& ~POWER_DOWN
, zx_pll
->reg_base
);
113 return readl_relaxed_poll_timeout(zx_pll
->reg_base
, reg
,
114 reg
& LOCK_FLAG
, 0, 100);
117 static void zx_pll_disable(struct clk_hw
*hw
)
119 struct clk_zx_pll
*zx_pll
= to_clk_zx_pll(hw
);
122 reg
= readl_relaxed(zx_pll
->reg_base
);
123 writel_relaxed(reg
| POWER_DOWN
, zx_pll
->reg_base
);
126 static int zx_pll_is_enabled(struct clk_hw
*hw
)
128 struct clk_zx_pll
*zx_pll
= to_clk_zx_pll(hw
);
131 reg
= readl_relaxed(zx_pll
->reg_base
);
133 return !(reg
& POWER_DOWN
);
136 static const struct clk_ops zx_pll_ops
= {
137 .recalc_rate
= zx_pll_recalc_rate
,
138 .round_rate
= zx_pll_round_rate
,
139 .set_rate
= zx_pll_set_rate
,
140 .enable
= zx_pll_enable
,
141 .disable
= zx_pll_disable
,
142 .is_enabled
= zx_pll_is_enabled
,
145 struct clk
*clk_register_zx_pll(const char *name
, const char *parent_name
,
146 unsigned long flags
, void __iomem
*reg_base
,
147 const struct zx_pll_config
*lookup_table
,
148 int count
, spinlock_t
*lock
)
150 struct clk_zx_pll
*zx_pll
;
152 struct clk_init_data init
;
154 zx_pll
= kzalloc(sizeof(*zx_pll
), GFP_KERNEL
);
156 return ERR_PTR(-ENOMEM
);
159 init
.ops
= &zx_pll_ops
;
161 init
.parent_names
= parent_name
? &parent_name
: NULL
;
162 init
.num_parents
= parent_name
? 1 : 0;
164 zx_pll
->reg_base
= reg_base
;
165 zx_pll
->lookup_table
= lookup_table
;
166 zx_pll
->count
= count
;
168 zx_pll
->hw
.init
= &init
;
170 clk
= clk_register(NULL
, &zx_pll
->hw
);
178 static u32
calc_reg(u32 parent_rate
, u32 rate
)
180 u32 sel
, integ
, fra_div
, tmp
;
181 u64 tmp64
= (u64
)parent_rate
* BPAR
;
184 integ
= (u32
)tmp64
/ BPAR
;
187 tmp
= (u32
)tmp64
% BPAR
;
191 fra_div
= tmp
* 0xff / BPAR
;
192 tmp
= (sel
<< 24) | (integ
<< 16) | (0xff << 8) | fra_div
;
194 /* Set I2S integer divider as 1. This bit is reserved for SPDIF
201 static u32
calc_rate(u32 reg
, u32 parent_rate
)
203 u32 sel
, integ
, fra_div
, tmp
;
204 u64 tmp64
= (u64
)parent_rate
* BPAR
;
207 sel
= (tmp
>> 24) & BIT(0);
208 integ
= (tmp
>> 16) & 0xff;
209 fra_div
= tmp
& 0xff;
211 tmp
= fra_div
* BPAR
;
214 tmp
+= 2 * integ
* BPAR
;
220 static unsigned long zx_audio_recalc_rate(struct clk_hw
*hw
,
221 unsigned long parent_rate
)
223 struct clk_zx_audio
*zx_audio
= to_clk_zx_audio(hw
);
226 reg
= readl_relaxed(zx_audio
->reg_base
);
227 return calc_rate(reg
, parent_rate
);
230 static long zx_audio_round_rate(struct clk_hw
*hw
, unsigned long rate
,
231 unsigned long *prate
)
235 if (rate
* 2 > *prate
)
238 reg
= calc_reg(*prate
, rate
);
239 return calc_rate(reg
, *prate
);
242 static int zx_audio_set_rate(struct clk_hw
*hw
, unsigned long rate
,
243 unsigned long parent_rate
)
245 struct clk_zx_audio
*zx_audio
= to_clk_zx_audio(hw
);
248 reg
= calc_reg(parent_rate
, rate
);
249 writel_relaxed(reg
, zx_audio
->reg_base
);
254 #define ZX_AUDIO_EN BIT(25)
255 static int zx_audio_enable(struct clk_hw
*hw
)
257 struct clk_zx_audio
*zx_audio
= to_clk_zx_audio(hw
);
260 reg
= readl_relaxed(zx_audio
->reg_base
);
261 writel_relaxed(reg
& ~ZX_AUDIO_EN
, zx_audio
->reg_base
);
265 static void zx_audio_disable(struct clk_hw
*hw
)
267 struct clk_zx_audio
*zx_audio
= to_clk_zx_audio(hw
);
270 reg
= readl_relaxed(zx_audio
->reg_base
);
271 writel_relaxed(reg
| ZX_AUDIO_EN
, zx_audio
->reg_base
);
274 static const struct clk_ops zx_audio_ops
= {
275 .recalc_rate
= zx_audio_recalc_rate
,
276 .round_rate
= zx_audio_round_rate
,
277 .set_rate
= zx_audio_set_rate
,
278 .enable
= zx_audio_enable
,
279 .disable
= zx_audio_disable
,
282 struct clk
*clk_register_zx_audio(const char *name
,
283 const char * const parent_name
,
285 void __iomem
*reg_base
)
287 struct clk_zx_audio
*zx_audio
;
289 struct clk_init_data init
;
291 zx_audio
= kzalloc(sizeof(*zx_audio
), GFP_KERNEL
);
293 return ERR_PTR(-ENOMEM
);
296 init
.ops
= &zx_audio_ops
;
298 init
.parent_names
= parent_name
? &parent_name
: NULL
;
299 init
.num_parents
= parent_name
? 1 : 0;
301 zx_audio
->reg_base
= reg_base
;
302 zx_audio
->hw
.init
= &init
;
304 clk
= clk_register(NULL
, &zx_audio
->hw
);