diff options
author | viresh kumar <viresh.kumar@st.com> | 2011-02-16 01:40:31 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-03-09 04:49:45 -0500 |
commit | cf285434ac0880f94bf4afdd90b06a4655f56570 (patch) | |
tree | 6b7b0f6716c17147e45cca39d01f88570d368eb5 /arch/arm/plat-spear | |
parent | 5c881d9ae9480171f01921585e1893863d7ab421 (diff) |
ARM: 6679/1: SPEAr: make clk API functions more generic
- Add a dummy clk_set_rate() function. This is required for compilation
of a few drivers.
- Make functions in plat-spear/clock.c more generic over all SPEAr
platforms.
- Add div_factor in struct clk for clks with .recalc = follow_parent
- Change type of register pointers to void __iomem *
Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-spear')
-rw-r--r-- | arch/arm/plat-spear/clock.c | 59 | ||||
-rw-r--r-- | arch/arm/plat-spear/include/plat/clock.h | 68 |
2 files changed, 97 insertions, 30 deletions
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c index ee4f90e534d8..f1cf832e4e3b 100644 --- a/arch/arm/plat-spear/clock.c +++ b/arch/arm/plat-spear/clock.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/list.h> | 17 | #include <linux/list.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <mach/misc_regs.h> | ||
21 | #include <plat/clock.h> | 20 | #include <plat/clock.h> |
22 | 21 | ||
23 | static DEFINE_SPINLOCK(clocks_lock); | 22 | static DEFINE_SPINLOCK(clocks_lock); |
@@ -187,6 +186,20 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
187 | } | 186 | } |
188 | EXPORT_SYMBOL(clk_set_parent); | 187 | EXPORT_SYMBOL(clk_set_parent); |
189 | 188 | ||
189 | /** | ||
190 | * clk_set_rate - set the clock rate for a clock source | ||
191 | * @clk: clock source | ||
192 | * @rate: desired clock rate in Hz | ||
193 | * | ||
194 | * Returns success (0) or negative errno. | ||
195 | */ | ||
196 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
197 | { | ||
198 | /* TODO */ | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | EXPORT_SYMBOL(clk_set_rate); | ||
202 | |||
190 | /* registers clock in platform clock framework */ | 203 | /* registers clock in platform clock framework */ |
191 | void clk_register(struct clk_lookup *cl) | 204 | void clk_register(struct clk_lookup *cl) |
192 | { | 205 | { |
@@ -212,6 +225,7 @@ void clk_register(struct clk_lookup *cl) | |||
212 | list_add(&clk->sibling, &clk->pclk->children); | 225 | list_add(&clk->sibling, &clk->pclk->children); |
213 | } else { | 226 | } else { |
214 | /* add clocks with > 1 parent to 1st parent's children list */ | 227 | /* add clocks with > 1 parent to 1st parent's children list */ |
228 | clk->pclk = clk->pclk_sel->pclk_info[0].pclk; | ||
215 | list_add(&clk->sibling, | 229 | list_add(&clk->sibling, |
216 | &clk->pclk_sel->pclk_info[0].pclk->children); | 230 | &clk->pclk_sel->pclk_info[0].pclk->children); |
217 | } | 231 | } |
@@ -283,29 +297,31 @@ static void change_parent(struct clk *cclk, struct clk *pclk) | |||
283 | * In Dithered mode | 297 | * In Dithered mode |
284 | * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) | 298 | * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) |
285 | */ | 299 | */ |
286 | void pll1_clk_recalc(struct clk *clk) | 300 | void pll_clk_recalc(struct clk *clk) |
287 | { | 301 | { |
288 | struct pll_clk_config *config = clk->private_data; | 302 | struct pll_clk_config *config = clk->private_data; |
289 | unsigned int num = 2, den = 0, val, mode = 0; | 303 | unsigned int num = 2, den = 0, val, mode = 0; |
290 | unsigned long flags; | 304 | unsigned long flags; |
291 | 305 | ||
292 | spin_lock_irqsave(&clocks_lock, flags); | 306 | spin_lock_irqsave(&clocks_lock, flags); |
293 | mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) & | 307 | mode = (readl(config->mode_reg) >> config->masks->mode_shift) & |
294 | PLL_MODE_MASK; | 308 | config->masks->mode_mask; |
295 | 309 | ||
296 | val = readl(config->cfg_reg); | 310 | val = readl(config->cfg_reg); |
297 | /* calculate denominator */ | 311 | /* calculate denominator */ |
298 | den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; | 312 | den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask; |
299 | den = 1 << den; | 313 | den = 1 << den; |
300 | den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; | 314 | den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask; |
301 | 315 | ||
302 | /* calculate numerator & denominator */ | 316 | /* calculate numerator & denominator */ |
303 | if (!mode) { | 317 | if (!mode) { |
304 | /* Normal mode */ | 318 | /* Normal mode */ |
305 | num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; | 319 | num *= (val >> config->masks->norm_fdbk_m_shift) & |
320 | config->masks->norm_fdbk_m_mask; | ||
306 | } else { | 321 | } else { |
307 | /* Dithered mode */ | 322 | /* Dithered mode */ |
308 | num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; | 323 | num *= (val >> config->masks->dith_fdbk_m_shift) & |
324 | config->masks->dith_fdbk_m_mask; | ||
309 | den *= 256; | 325 | den *= 256; |
310 | } | 326 | } |
311 | 327 | ||
@@ -321,7 +337,8 @@ void bus_clk_recalc(struct clk *clk) | |||
321 | unsigned long flags; | 337 | unsigned long flags; |
322 | 338 | ||
323 | spin_lock_irqsave(&clocks_lock, flags); | 339 | spin_lock_irqsave(&clocks_lock, flags); |
324 | div = ((readl(config->reg) >> config->shift) & config->mask) + 1; | 340 | div = ((readl(config->reg) >> config->masks->shift) & |
341 | config->masks->mask) + 1; | ||
325 | clk->rate = (unsigned long)clk->pclk->rate / div; | 342 | clk->rate = (unsigned long)clk->pclk->rate / div; |
326 | spin_unlock_irqrestore(&clocks_lock, flags); | 343 | spin_unlock_irqrestore(&clocks_lock, flags); |
327 | } | 344 | } |
@@ -359,15 +376,18 @@ void aux_clk_recalc(struct clk *clk) | |||
359 | if (pclk_info->scalable) { | 376 | if (pclk_info->scalable) { |
360 | val = readl(config->synth_reg); | 377 | val = readl(config->synth_reg); |
361 | 378 | ||
362 | eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK; | 379 | eqn = (val >> config->masks->eq_sel_shift) & |
363 | if (eqn == AUX_EQ1_SEL) | 380 | config->masks->eq_sel_mask; |
381 | if (eqn == config->masks->eq1_mask) | ||
364 | den *= 2; | 382 | den *= 2; |
365 | 383 | ||
366 | /* calculate numerator */ | 384 | /* calculate numerator */ |
367 | num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK; | 385 | num = (val >> config->masks->xscale_sel_shift) & |
386 | config->masks->xscale_sel_mask; | ||
368 | 387 | ||
369 | /* calculate denominator */ | 388 | /* calculate denominator */ |
370 | den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK; | 389 | den *= (val >> config->masks->yscale_sel_shift) & |
390 | config->masks->yscale_sel_mask; | ||
371 | val = (((clk->pclk->rate/10000) * num) / den) * 10000; | 391 | val = (((clk->pclk->rate/10000) * num) / den) * 10000; |
372 | } else | 392 | } else |
373 | val = clk->pclk->rate; | 393 | val = clk->pclk->rate; |
@@ -383,7 +403,7 @@ void aux_clk_recalc(struct clk *clk) | |||
383 | */ | 403 | */ |
384 | void gpt_clk_recalc(struct clk *clk) | 404 | void gpt_clk_recalc(struct clk *clk) |
385 | { | 405 | { |
386 | struct aux_clk_config *config = clk->private_data; | 406 | struct gpt_clk_config *config = clk->private_data; |
387 | struct pclk_info *pclk_info = NULL; | 407 | struct pclk_info *pclk_info = NULL; |
388 | unsigned int div = 1, val; | 408 | unsigned int div = 1, val; |
389 | unsigned long flags; | 409 | unsigned long flags; |
@@ -402,8 +422,10 @@ void gpt_clk_recalc(struct clk *clk) | |||
402 | spin_lock_irqsave(&clocks_lock, flags); | 422 | spin_lock_irqsave(&clocks_lock, flags); |
403 | if (pclk_info->scalable) { | 423 | if (pclk_info->scalable) { |
404 | val = readl(config->synth_reg); | 424 | val = readl(config->synth_reg); |
405 | div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK; | 425 | div += (val >> config->masks->mscale_sel_shift) & |
406 | div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1); | 426 | config->masks->mscale_sel_mask; |
427 | div *= 1 << (((val >> config->masks->nscale_sel_shift) & | ||
428 | config->masks->nscale_sel_mask) + 1); | ||
407 | } | 429 | } |
408 | 430 | ||
409 | clk->rate = (unsigned long)clk->pclk->rate / div; | 431 | clk->rate = (unsigned long)clk->pclk->rate / div; |
@@ -411,15 +433,16 @@ void gpt_clk_recalc(struct clk *clk) | |||
411 | } | 433 | } |
412 | 434 | ||
413 | /* | 435 | /* |
414 | * Used for clocks that always have same value as the parent clock divided by a | 436 | * Used for clocks that always have value as the parent clock divided by a |
415 | * fixed divisor | 437 | * fixed divisor |
416 | */ | 438 | */ |
417 | void follow_parent(struct clk *clk) | 439 | void follow_parent(struct clk *clk) |
418 | { | 440 | { |
419 | unsigned long flags; | 441 | unsigned long flags; |
442 | unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor; | ||
420 | 443 | ||
421 | spin_lock_irqsave(&clocks_lock, flags); | 444 | spin_lock_irqsave(&clocks_lock, flags); |
422 | clk->rate = clk->pclk->rate; | 445 | clk->rate = clk->pclk->rate/div_factor; |
423 | spin_unlock_irqrestore(&clocks_lock, flags); | 446 | spin_unlock_irqrestore(&clocks_lock, flags); |
424 | } | 447 | } |
425 | 448 | ||
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h index 2572260f990f..863d9e983927 100644 --- a/arch/arm/plat-spear/include/plat/clock.h +++ b/arch/arm/plat-spear/include/plat/clock.h | |||
@@ -54,7 +54,7 @@ struct pclk_info { | |||
54 | struct pclk_sel { | 54 | struct pclk_sel { |
55 | struct pclk_info *pclk_info; | 55 | struct pclk_info *pclk_info; |
56 | u8 pclk_count; | 56 | u8 pclk_count; |
57 | unsigned int *pclk_sel_reg; | 57 | void __iomem *pclk_sel_reg; |
58 | unsigned int pclk_sel_mask; | 58 | unsigned int pclk_sel_mask; |
59 | }; | 59 | }; |
60 | 60 | ||
@@ -67,6 +67,7 @@ struct pclk_sel { | |||
67 | * @en_reg_bit: clk enable/disable bit | 67 | * @en_reg_bit: clk enable/disable bit |
68 | * @ops: clk enable/disable ops - generic_clkops selected if NULL | 68 | * @ops: clk enable/disable ops - generic_clkops selected if NULL |
69 | * @recalc: pointer to clock rate recalculate function | 69 | * @recalc: pointer to clock rate recalculate function |
70 | * @div_factor: division factor to parent clock. Only for recalc = follow_parent | ||
70 | * @pclk: current parent clk | 71 | * @pclk: current parent clk |
71 | * @pclk_sel: pointer to parent selection structure | 72 | * @pclk_sel: pointer to parent selection structure |
72 | * @pclk_sel_shift: register shift for selecting parent of this clock | 73 | * @pclk_sel_shift: register shift for selecting parent of this clock |
@@ -78,10 +79,11 @@ struct clk { | |||
78 | unsigned int usage_count; | 79 | unsigned int usage_count; |
79 | unsigned int flags; | 80 | unsigned int flags; |
80 | unsigned long rate; | 81 | unsigned long rate; |
81 | unsigned int *en_reg; | 82 | void __iomem *en_reg; |
82 | u8 en_reg_bit; | 83 | u8 en_reg_bit; |
83 | const struct clkops *ops; | 84 | const struct clkops *ops; |
84 | void (*recalc) (struct clk *); | 85 | void (*recalc) (struct clk *); |
86 | unsigned int div_factor; | ||
85 | 87 | ||
86 | struct clk *pclk; | 88 | struct clk *pclk; |
87 | struct pclk_sel *pclk_sel; | 89 | struct pclk_sel *pclk_sel; |
@@ -93,23 +95,65 @@ struct clk { | |||
93 | }; | 95 | }; |
94 | 96 | ||
95 | /* pll configuration structure */ | 97 | /* pll configuration structure */ |
98 | struct pll_clk_masks { | ||
99 | u32 mode_mask; | ||
100 | u32 mode_shift; | ||
101 | |||
102 | u32 norm_fdbk_m_mask; | ||
103 | u32 norm_fdbk_m_shift; | ||
104 | u32 dith_fdbk_m_mask; | ||
105 | u32 dith_fdbk_m_shift; | ||
106 | u32 div_p_mask; | ||
107 | u32 div_p_shift; | ||
108 | u32 div_n_mask; | ||
109 | u32 div_n_shift; | ||
110 | }; | ||
111 | |||
96 | struct pll_clk_config { | 112 | struct pll_clk_config { |
97 | unsigned int *mode_reg; | 113 | void __iomem *mode_reg; |
98 | unsigned int *cfg_reg; | 114 | void __iomem *cfg_reg; |
115 | struct pll_clk_masks *masks; | ||
99 | }; | 116 | }; |
100 | 117 | ||
101 | /* ahb and apb bus configuration structure */ | 118 | /* ahb and apb bus configuration structure */ |
119 | struct bus_clk_masks { | ||
120 | u32 mask; | ||
121 | u32 shift; | ||
122 | }; | ||
123 | |||
102 | struct bus_clk_config { | 124 | struct bus_clk_config { |
103 | unsigned int *reg; | 125 | void __iomem *reg; |
104 | unsigned int mask; | 126 | struct bus_clk_masks *masks; |
105 | unsigned int shift; | 127 | }; |
128 | |||
129 | /* Aux clk configuration structure: applicable to UART and FIRDA */ | ||
130 | struct aux_clk_masks { | ||
131 | u32 eq_sel_mask; | ||
132 | u32 eq_sel_shift; | ||
133 | u32 eq1_mask; | ||
134 | u32 eq2_mask; | ||
135 | u32 xscale_sel_mask; | ||
136 | u32 xscale_sel_shift; | ||
137 | u32 yscale_sel_mask; | ||
138 | u32 yscale_sel_shift; | ||
106 | }; | 139 | }; |
107 | 140 | ||
108 | /* | ||
109 | * Aux clk configuration structure: applicable to GPT, UART and FIRDA | ||
110 | */ | ||
111 | struct aux_clk_config { | 141 | struct aux_clk_config { |
112 | unsigned int *synth_reg; | 142 | void __iomem *synth_reg; |
143 | struct aux_clk_masks *masks; | ||
144 | }; | ||
145 | |||
146 | /* GPT clk configuration structure */ | ||
147 | struct gpt_clk_masks { | ||
148 | u32 mscale_sel_mask; | ||
149 | u32 mscale_sel_shift; | ||
150 | u32 nscale_sel_mask; | ||
151 | u32 nscale_sel_shift; | ||
152 | }; | ||
153 | |||
154 | struct gpt_clk_config { | ||
155 | void __iomem *synth_reg; | ||
156 | struct gpt_clk_masks *masks; | ||
113 | }; | 157 | }; |
114 | 158 | ||
115 | /* platform specific clock functions */ | 159 | /* platform specific clock functions */ |
@@ -118,7 +162,7 @@ void recalc_root_clocks(void); | |||
118 | 162 | ||
119 | /* clock recalc functions */ | 163 | /* clock recalc functions */ |
120 | void follow_parent(struct clk *clk); | 164 | void follow_parent(struct clk *clk); |
121 | void pll1_clk_recalc(struct clk *clk); | 165 | void pll_clk_recalc(struct clk *clk); |
122 | void bus_clk_recalc(struct clk *clk); | 166 | void bus_clk_recalc(struct clk *clk); |
123 | void gpt_clk_recalc(struct clk *clk); | 167 | void gpt_clk_recalc(struct clk *clk); |
124 | void aux_clk_recalc(struct clk *clk); | 168 | void aux_clk_recalc(struct clk *clk); |