diff options
author | Olof Johansson <olof@lixom.net> | 2012-02-07 18:13:59 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-02-07 18:13:59 -0500 |
commit | 88b1988ec2337f5fd8b9204a919838d0bc34b7b4 (patch) | |
tree | cc6e781cd62a46ac8117f6838c95b805df639aad /arch/arm/mach-mxs | |
parent | afd96f8335dd1f54bf41a3485c564dfb50f490c5 (diff) | |
parent | 444a7c3bb897ec6a64b83d277102440c1dcc22a1 (diff) |
Merge branch 'mxs/clk' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc
* 'mxs/clk' of git://git.linaro.org/people/shawnguo/linux-2.6:
ARM: mxs: Use a proper timeout mechanism
ARM: mx28: check for gated clocks when setting saif divider
arm/mxs: Add support for SSP/MMC ports 2 & 3
Diffstat (limited to 'arch/arm/mach-mxs')
-rw-r--r-- | arch/arm/mach-mxs/clock-mx23.c | 34 | ||||
-rw-r--r-- | arch/arm/mach-mxs/clock-mx28.c | 57 | ||||
-rw-r--r-- | arch/arm/mach-mxs/devices/platform-mxs-mmc.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-mxs/include/mach/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-mxs/system.c | 16 |
5 files changed, 39 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[] = { | |||
461 | static int clk_misc_init(void) | 444 | static 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 | ||
538 | int __init mx23_clocks_init(void) | 514 | int __init mx23_clocks_init(void) |
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 5d68e4152220..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) \ |
@@ -477,18 +456,13 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ | |||
477 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \ | 456 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \ |
478 | reg &= ~BM_CLKCTRL_##rs##_DIV; \ | 457 | reg &= ~BM_CLKCTRL_##rs##_DIV; \ |
479 | reg |= div << BP_CLKCTRL_##rs##_DIV; \ | 458 | reg |= div << BP_CLKCTRL_##rs##_DIV; \ |
480 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \ | 459 | if (reg & (1 << clk->enable_shift)) { \ |
481 | \ | 460 | pr_err("%s: clock is gated\n", __func__); \ |
482 | for (i = 10000; i; i--) \ | 461 | return -EINVAL; \ |
483 | if (!(__raw_readl(CLKCTRL_BASE_ADDR + \ | ||
484 | HW_CLKCTRL_##rs) & BM_CLKCTRL_##rs##_BUSY)) \ | ||
485 | break; \ | ||
486 | if (!i) { \ | ||
487 | pr_err("%s: divider writing timeout\n", __func__); \ | ||
488 | return -ETIMEDOUT; \ | ||
489 | } \ | 462 | } \ |
463 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \ | ||
490 | \ | 464 | \ |
491 | return 0; \ | 465 | return mxs_clkctrl_timeout(HW_CLKCTRL_##rs, BM_CLKCTRL_##rs##_BUSY);\ |
492 | } | 466 | } |
493 | 467 | ||
494 | _CLK_SET_RATE_SAIF(saif0_clk, SAIF0) | 468 | _CLK_SET_RATE_SAIF(saif0_clk, SAIF0) |
@@ -654,6 +628,8 @@ static struct clk_lookup lookups[] = { | |||
654 | _REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk) | 628 | _REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk) |
655 | _REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk) | 629 | _REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk) |
656 | _REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk) | 630 | _REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk) |
631 | _REGISTER_CLOCK("mxs-mmc.2", NULL, ssp2_clk) | ||
632 | _REGISTER_CLOCK("mxs-mmc.3", NULL, ssp3_clk) | ||
657 | _REGISTER_CLOCK("flexcan.0", NULL, can0_clk) | 633 | _REGISTER_CLOCK("flexcan.0", NULL, can0_clk) |
658 | _REGISTER_CLOCK("flexcan.1", NULL, can1_clk) | 634 | _REGISTER_CLOCK("flexcan.1", NULL, can1_clk) |
659 | _REGISTER_CLOCK(NULL, "usb0", usb0_clk) | 635 | _REGISTER_CLOCK(NULL, "usb0", usb0_clk) |
@@ -676,7 +652,7 @@ static struct clk_lookup lookups[] = { | |||
676 | static int clk_misc_init(void) | 652 | static int clk_misc_init(void) |
677 | { | 653 | { |
678 | u32 reg; | 654 | u32 reg; |
679 | int i; | 655 | int ret; |
680 | 656 | ||
681 | /* Fix up parent per register setting */ | 657 | /* Fix up parent per register setting */ |
682 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ); | 658 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ); |
@@ -756,14 +732,7 @@ static int clk_misc_init(void) | |||
756 | reg |= 3 << BP_CLKCTRL_HBUS_DIV; | 732 | reg |= 3 << BP_CLKCTRL_HBUS_DIV; |
757 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); | 733 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); |
758 | 734 | ||
759 | for (i = 10000; i; i--) | 735 | ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_ASM_BUSY); |
760 | if (!(__raw_readl(CLKCTRL_BASE_ADDR + | ||
761 | HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_ASM_BUSY)) | ||
762 | break; | ||
763 | if (!i) { | ||
764 | pr_err("%s: divider writing timeout\n", __func__); | ||
765 | return -ETIMEDOUT; | ||
766 | } | ||
767 | 736 | ||
768 | /* Gate off cpu clock in WFI for power saving */ | 737 | /* Gate off cpu clock in WFI for power saving */ |
769 | __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, | 738 | __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, |
@@ -790,7 +759,7 @@ static int clk_misc_init(void) | |||
790 | reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC; | 759 | reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC; |
791 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0); | 760 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0); |
792 | 761 | ||
793 | return 0; | 762 | return ret; |
794 | } | 763 | } |
795 | 764 | ||
796 | int __init mx28_clocks_init(void) | 765 | int __init mx28_clocks_init(void) |
@@ -803,6 +772,8 @@ int __init mx28_clocks_init(void) | |||
803 | */ | 772 | */ |
804 | clk_set_parent(&ssp0_clk, &ref_io0_clk); | 773 | clk_set_parent(&ssp0_clk, &ref_io0_clk); |
805 | clk_set_parent(&ssp1_clk, &ref_io0_clk); | 774 | clk_set_parent(&ssp1_clk, &ref_io0_clk); |
775 | clk_set_parent(&ssp2_clk, &ref_io1_clk); | ||
776 | clk_set_parent(&ssp3_clk, &ref_io1_clk); | ||
806 | 777 | ||
807 | clk_prepare_enable(&cpu_clk); | 778 | clk_prepare_enable(&cpu_clk); |
808 | clk_prepare_enable(&hbus_clk); | 779 | clk_prepare_enable(&hbus_clk); |
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c index 382dacbeca21..bef9d923f54e 100644 --- a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c +++ b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c | |||
@@ -41,6 +41,8 @@ const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = { | |||
41 | const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = { | 41 | const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = { |
42 | mxs_mxs_mmc_data_entry(MX28, 0, 0), | 42 | mxs_mxs_mmc_data_entry(MX28, 0, 0), |
43 | mxs_mxs_mmc_data_entry(MX28, 1, 1), | 43 | mxs_mxs_mmc_data_entry(MX28, 1, 1), |
44 | mxs_mxs_mmc_data_entry(MX28, 2, 2), | ||
45 | mxs_mxs_mmc_data_entry(MX28, 3, 3), | ||
44 | }; | 46 | }; |
45 | #endif | 47 | #endif |
46 | 48 | ||
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 | ||
32 | extern void icoll_init_irq(void); | 32 | extern void icoll_init_irq(void); |
33 | 33 | ||
34 | extern 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 | |||
40 | static void __iomem *mxs_clkctrl_reset_addr; | 42 | static void __iomem *mxs_clkctrl_reset_addr; |
41 | 43 | ||
42 | /* | 44 | /* |
@@ -137,3 +139,17 @@ error: | |||
137 | return -ETIMEDOUT; | 139 | return -ETIMEDOUT; |
138 | } | 140 | } |
139 | EXPORT_SYMBOL(mxs_reset_block); | 141 | EXPORT_SYMBOL(mxs_reset_block); |
142 | |||
143 | int 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 | } | ||