aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mxs
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@freescale.com>2012-01-27 09:44:29 -0500
committerShawn Guo <shawn.guo@linaro.org>2012-01-31 09:42:15 -0500
commit444a7c3bb897ec6a64b83d277102440c1dcc22a1 (patch)
treef6168d81c13b5e7641ca815bd5703fdee3adc5f5 /arch/arm/mach-mxs
parenta62407256bbcba8e3f62695a87534050ceec0e6f (diff)
ARM: mxs: Use a proper timeout mechanism
Introduce a function for checking the busy bits of CLKCTRL register that uses a proper timeout mechanism. Remove parts of code that use busy loops and replace them with the mxs_clkctrl_timeout() function. Tested on a mx28evk by performing audio playback. Suggested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'arch/arm/mach-mxs')
-rw-r--r--arch/arm/mach-mxs/clock-mx23.c34
-rw-r--r--arch/arm/mach-mxs/clock-mx28.c49
-rw-r--r--arch/arm/mach-mxs/include/mach/common.h2
-rw-r--r--arch/arm/mach-mxs/system.c16
4 files changed, 29 insertions, 72 deletions
diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index e12e11231dc7..293958beb505 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -223,7 +223,6 @@ static int cpu_clk_set_rate(struct clk *clk, unsigned long rate)
223{ 223{
224 u32 reg, bm_busy, div_max, d, f, div, frac; 224 u32 reg, bm_busy, div_max, d, f, div, frac;
225 unsigned long diff, parent_rate, calc_rate; 225 unsigned long diff, parent_rate, calc_rate;
226 int i;
227 226
228 parent_rate = clk_get_rate(clk->parent); 227 parent_rate = clk_get_rate(clk->parent);
229 228
@@ -275,14 +274,7 @@ static int cpu_clk_set_rate(struct clk *clk, unsigned long rate)
275 reg |= div << BP_CLKCTRL_CPU_DIV_CPU; 274 reg |= div << BP_CLKCTRL_CPU_DIV_CPU;
276 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU); 275 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);
277 276
278 for (i = 10000; i; i--) 277 mxs_clkctrl_timeout(HW_CLKCTRL_CPU, bm_busy);
279 if (!(__raw_readl(CLKCTRL_BASE_ADDR +
280 HW_CLKCTRL_CPU) & bm_busy))
281 break;
282 if (!i) {
283 pr_err("%s: divider writing timeout\n", __func__);
284 return -ETIMEDOUT;
285 }
286 278
287 return 0; 279 return 0;
288} 280}
@@ -292,7 +284,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
292{ \ 284{ \
293 u32 reg, div_max, div; \ 285 u32 reg, div_max, div; \
294 unsigned long parent_rate; \ 286 unsigned long parent_rate; \
295 int i; \
296 \ 287 \
297 parent_rate = clk_get_rate(clk->parent); \ 288 parent_rate = clk_get_rate(clk->parent); \
298 div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \ 289 div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
@@ -310,15 +301,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
310 } \ 301 } \
311 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ 302 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
312 \ 303 \
313 for (i = 10000; i; i--) \ 304 mxs_clkctrl_timeout(HW_CLKCTRL_##dr, BM_CLKCTRL_##dr##_BUSY); \
314 if (!(__raw_readl(CLKCTRL_BASE_ADDR + \
315 HW_CLKCTRL_##dr) & BM_CLKCTRL_##dr##_BUSY)) \
316 break; \
317 if (!i) { \
318 pr_err("%s: divider writing timeout\n", __func__); \
319 return -ETIMEDOUT; \
320 } \
321 \
322 return 0; \ 305 return 0; \
323} 306}
324 307
@@ -461,7 +444,7 @@ static struct clk_lookup lookups[] = {
461static int clk_misc_init(void) 444static int clk_misc_init(void)
462{ 445{
463 u32 reg; 446 u32 reg;
464 int i; 447 int ret;
465 448
466 /* Fix up parent per register setting */ 449 /* Fix up parent per register setting */
467 reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ); 450 reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
@@ -510,14 +493,7 @@ static int clk_misc_init(void)
510 reg |= 3 << BP_CLKCTRL_HBUS_DIV; 493 reg |= 3 << BP_CLKCTRL_HBUS_DIV;
511 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); 494 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
512 495
513 for (i = 10000; i; i--) 496 ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_BUSY);
514 if (!(__raw_readl(CLKCTRL_BASE_ADDR +
515 HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_BUSY))
516 break;
517 if (!i) {
518 pr_err("%s: divider writing timeout\n", __func__);
519 return -ETIMEDOUT;
520 }
521 497
522 /* Gate off cpu clock in WFI for power saving */ 498 /* Gate off cpu clock in WFI for power saving */
523 __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, 499 __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
@@ -532,7 +508,7 @@ static int clk_misc_init(void)
532 reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC; 508 reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC;
533 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC); 509 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
534 510
535 return 0; 511 return ret;
536} 512}
537 513
538int __init mx23_clocks_init(void) 514int __init mx23_clocks_init(void)
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 54d82a4b4cf0..22ad12f6e4de 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -322,7 +322,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
322{ \ 322{ \
323 u32 reg, bm_busy, div_max, d, f, div, frac; \ 323 u32 reg, bm_busy, div_max, d, f, div, frac; \
324 unsigned long diff, parent_rate, calc_rate; \ 324 unsigned long diff, parent_rate, calc_rate; \
325 int i; \
326 \ 325 \
327 div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \ 326 div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
328 bm_busy = BM_CLKCTRL_##dr##_BUSY; \ 327 bm_busy = BM_CLKCTRL_##dr##_BUSY; \
@@ -396,16 +395,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
396 } \ 395 } \
397 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ 396 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
398 \ 397 \
399 for (i = 10000; i; i--) \ 398 return mxs_clkctrl_timeout(HW_CLKCTRL_##dr, bm_busy); \
400 if (!(__raw_readl(CLKCTRL_BASE_ADDR + \
401 HW_CLKCTRL_##dr) & bm_busy)) \
402 break; \
403 if (!i) { \
404 pr_err("%s: divider writing timeout\n", __func__); \
405 return -ETIMEDOUT; \
406 } \
407 \
408 return 0; \
409} 399}
410 400
411_CLK_SET_RATE(cpu_clk, CPU, FRAC0, CPU) 401_CLK_SET_RATE(cpu_clk, CPU, FRAC0, CPU)
@@ -421,7 +411,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
421{ \ 411{ \
422 u32 reg, div_max, div; \ 412 u32 reg, div_max, div; \
423 unsigned long parent_rate; \ 413 unsigned long parent_rate; \
424 int i; \
425 \ 414 \
426 parent_rate = clk_get_rate(clk->parent); \ 415 parent_rate = clk_get_rate(clk->parent); \
427 div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \ 416 div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
@@ -439,16 +428,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
439 } \ 428 } \
440 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ 429 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
441 \ 430 \
442 for (i = 10000; i; i--) \ 431 return mxs_clkctrl_timeout(HW_CLKCTRL_##dr, BM_CLKCTRL_##dr##_BUSY);\
443 if (!(__raw_readl(CLKCTRL_BASE_ADDR + \
444 HW_CLKCTRL_##dr) & BM_CLKCTRL_##dr##_BUSY)) \
445 break; \
446 if (!i) { \
447 pr_err("%s: divider writing timeout\n", __func__); \
448 return -ETIMEDOUT; \
449 } \
450 \
451 return 0; \
452} 432}
453 433
454_CLK_SET_RATE1(xbus_clk, XBUS) 434_CLK_SET_RATE1(xbus_clk, XBUS)
@@ -461,7 +441,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
461 u32 reg; \ 441 u32 reg; \
462 u64 lrate; \ 442 u64 lrate; \
463 unsigned long parent_rate; \ 443 unsigned long parent_rate; \
464 int i; \
465 \ 444 \
466 parent_rate = clk_get_rate(clk->parent); \ 445 parent_rate = clk_get_rate(clk->parent); \
467 if (rate > parent_rate) \ 446 if (rate > parent_rate) \
@@ -483,16 +462,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
483 } \ 462 } \
484 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \ 463 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
485 \ 464 \
486 for (i = 10000; i; i--) \ 465 return mxs_clkctrl_timeout(HW_CLKCTRL_##rs, BM_CLKCTRL_##rs##_BUSY);\
487 if (!(__raw_readl(CLKCTRL_BASE_ADDR + \
488 HW_CLKCTRL_##rs) & BM_CLKCTRL_##rs##_BUSY)) \
489 break; \
490 if (!i) { \
491 pr_err("%s: divider writing timeout\n", __func__); \
492 return -ETIMEDOUT; \
493 } \
494 \
495 return 0; \
496} 466}
497 467
498_CLK_SET_RATE_SAIF(saif0_clk, SAIF0) 468_CLK_SET_RATE_SAIF(saif0_clk, SAIF0)
@@ -682,7 +652,7 @@ static struct clk_lookup lookups[] = {
682static int clk_misc_init(void) 652static int clk_misc_init(void)
683{ 653{
684 u32 reg; 654 u32 reg;
685 int i; 655 int ret;
686 656
687 /* Fix up parent per register setting */ 657 /* Fix up parent per register setting */
688 reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ); 658 reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
@@ -762,14 +732,7 @@ static int clk_misc_init(void)
762 reg |= 3 << BP_CLKCTRL_HBUS_DIV; 732 reg |= 3 << BP_CLKCTRL_HBUS_DIV;
763 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); 733 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
764 734
765 for (i = 10000; i; i--) 735 ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_ASM_BUSY);
766 if (!(__raw_readl(CLKCTRL_BASE_ADDR +
767 HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_ASM_BUSY))
768 break;
769 if (!i) {
770 pr_err("%s: divider writing timeout\n", __func__);
771 return -ETIMEDOUT;
772 }
773 736
774 /* Gate off cpu clock in WFI for power saving */ 737 /* Gate off cpu clock in WFI for power saving */
775 __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, 738 __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
@@ -796,7 +759,7 @@ static int clk_misc_init(void)
796 reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC; 759 reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC;
797 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0); 760 __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
798 761
799 return 0; 762 return ret;
800} 763}
801 764
802int __init mx28_clocks_init(void) 765int __init mx28_clocks_init(void)
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
index e1237ab25862..c50c3ea28a9d 100644
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -31,4 +31,6 @@ extern void mx28_init_irq(void);
31 31
32extern void icoll_init_irq(void); 32extern void icoll_init_irq(void);
33 33
34extern int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask);
35
34#endif /* __MACH_MXS_COMMON_H__ */ 36#endif /* __MACH_MXS_COMMON_H__ */
diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
index 54f91ad1c965..7aa5ac5d78bf 100644
--- a/arch/arm/mach-mxs/system.c
+++ b/arch/arm/mach-mxs/system.c
@@ -37,6 +37,8 @@
37#define MXS_MODULE_CLKGATE (1 << 30) 37#define MXS_MODULE_CLKGATE (1 << 30)
38#define MXS_MODULE_SFTRST (1 << 31) 38#define MXS_MODULE_SFTRST (1 << 31)
39 39
40#define CLKCTRL_TIMEOUT 10 /* 10 ms */
41
40static void __iomem *mxs_clkctrl_reset_addr; 42static void __iomem *mxs_clkctrl_reset_addr;
41 43
42/* 44/*
@@ -137,3 +139,17 @@ error:
137 return -ETIMEDOUT; 139 return -ETIMEDOUT;
138} 140}
139EXPORT_SYMBOL(mxs_reset_block); 141EXPORT_SYMBOL(mxs_reset_block);
142
143int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask)
144{
145 unsigned long timeout = jiffies + msecs_to_jiffies(CLKCTRL_TIMEOUT);
146 while (readl_relaxed(MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR)
147 + reg_offset) & mask) {
148 if (time_after(jiffies, timeout)) {
149 pr_err("Timeout at CLKCTRL + 0x%x\n", reg_offset);
150 return -ETIMEDOUT;
151 }
152 }
153
154 return 0;
155}