aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-spear
diff options
context:
space:
mode:
authorviresh kumar <viresh.kumar@st.com>2011-02-16 01:40:31 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-03-09 04:49:45 -0500
commitcf285434ac0880f94bf4afdd90b06a4655f56570 (patch)
tree6b7b0f6716c17147e45cca39d01f88570d368eb5 /arch/arm/plat-spear
parent5c881d9ae9480171f01921585e1893863d7ab421 (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.c59
-rw-r--r--arch/arm/plat-spear/include/plat/clock.h68
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
23static DEFINE_SPINLOCK(clocks_lock); 22static DEFINE_SPINLOCK(clocks_lock);
@@ -187,6 +186,20 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
187} 186}
188EXPORT_SYMBOL(clk_set_parent); 187EXPORT_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 */
196int clk_set_rate(struct clk *clk, unsigned long rate)
197{
198 /* TODO */
199 return -EINVAL;
200}
201EXPORT_SYMBOL(clk_set_rate);
202
190/* registers clock in platform clock framework */ 203/* registers clock in platform clock framework */
191void clk_register(struct clk_lookup *cl) 204void 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 */
286void pll1_clk_recalc(struct clk *clk) 300void 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 */
384void gpt_clk_recalc(struct clk *clk) 404void 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 */
417void follow_parent(struct clk *clk) 439void 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 {
54struct pclk_sel { 54struct 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 */
98struct 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
96struct pll_clk_config { 112struct 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 */
119struct bus_clk_masks {
120 u32 mask;
121 u32 shift;
122};
123
102struct bus_clk_config { 124struct 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 */
130struct 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 */
111struct aux_clk_config { 141struct 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 */
147struct 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
154struct 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 */
120void follow_parent(struct clk *clk); 164void follow_parent(struct clk *clk);
121void pll1_clk_recalc(struct clk *clk); 165void pll_clk_recalc(struct clk *clk);
122void bus_clk_recalc(struct clk *clk); 166void bus_clk_recalc(struct clk *clk);
123void gpt_clk_recalc(struct clk *clk); 167void gpt_clk_recalc(struct clk *clk);
124void aux_clk_recalc(struct clk *clk); 168void aux_clk_recalc(struct clk *clk);