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/clock.c | |
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/clock.c')
-rw-r--r-- | arch/arm/plat-spear/clock.c | 59 |
1 files changed, 41 insertions, 18 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 | ||