diff options
Diffstat (limited to 'arch/arm/mach-mxs/clock-mx28.c')
-rw-r--r-- | arch/arm/mach-mxs/clock-mx28.c | 76 |
1 files changed, 62 insertions, 14 deletions
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 5dcc59d5b9ec..5d68e4152220 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/jiffies.h> | 23 | #include <linux/jiffies.h> |
24 | #include <linux/clkdev.h> | 24 | #include <linux/clkdev.h> |
25 | #include <linux/spinlock.h> | ||
25 | 26 | ||
26 | #include <asm/clkdev.h> | 27 | #include <asm/clkdev.h> |
27 | #include <asm/div64.h> | 28 | #include <asm/div64.h> |
@@ -29,6 +30,7 @@ | |||
29 | #include <mach/mx28.h> | 30 | #include <mach/mx28.h> |
30 | #include <mach/common.h> | 31 | #include <mach/common.h> |
31 | #include <mach/clock.h> | 32 | #include <mach/clock.h> |
33 | #include <mach/digctl.h> | ||
32 | 34 | ||
33 | #include "regs-clkctrl-mx28.h" | 35 | #include "regs-clkctrl-mx28.h" |
34 | 36 | ||
@@ -43,6 +45,33 @@ static struct clk emi_clk; | |||
43 | static struct clk saif0_clk; | 45 | static struct clk saif0_clk; |
44 | static struct clk saif1_clk; | 46 | static struct clk saif1_clk; |
45 | static struct clk clk32k_clk; | 47 | static struct clk clk32k_clk; |
48 | static DEFINE_SPINLOCK(clkmux_lock); | ||
49 | |||
50 | /* | ||
51 | * HW_SAIF_CLKMUX_SEL: | ||
52 | * DIRECT(0x0): SAIF0 clock pins selected for SAIF0 input clocks, and SAIF1 | ||
53 | * clock pins selected for SAIF1 input clocks. | ||
54 | * CROSSINPUT(0x1): SAIF1 clock inputs selected for SAIF0 input clocks, and | ||
55 | * SAIF0 clock inputs selected for SAIF1 input clocks. | ||
56 | * EXTMSTR0(0x2): SAIF0 clock pin selected for both SAIF0 and SAIF1 input | ||
57 | * clocks. | ||
58 | * EXTMSTR1(0x3): SAIF1 clock pin selected for both SAIF0 and SAIF1 input | ||
59 | * clocks. | ||
60 | */ | ||
61 | int mxs_saif_clkmux_select(unsigned int clkmux) | ||
62 | { | ||
63 | if (clkmux > 0x3) | ||
64 | return -EINVAL; | ||
65 | |||
66 | spin_lock(&clkmux_lock); | ||
67 | __raw_writel(BM_DIGCTL_CTRL_SAIF_CLKMUX, | ||
68 | DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_CLR_ADDR); | ||
69 | __raw_writel(clkmux << BP_DIGCTL_CTRL_SAIF_CLKMUX, | ||
70 | DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_SET_ADDR); | ||
71 | spin_unlock(&clkmux_lock); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
46 | 75 | ||
47 | static int _raw_clk_enable(struct clk *clk) | 76 | static int _raw_clk_enable(struct clk *clk) |
48 | { | 77 | { |
@@ -349,7 +378,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ | |||
349 | \ | 378 | \ |
350 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \ | 379 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \ |
351 | reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC; \ | 380 | reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC; \ |
352 | reg |= frac; \ | 381 | reg |= frac << BP_CLKCTRL_##fr##_##fs##FRAC; \ |
353 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \ | 382 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \ |
354 | } \ | 383 | } \ |
355 | \ | 384 | \ |
@@ -404,7 +433,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ | |||
404 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ | 433 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ |
405 | reg &= ~BM_CLKCTRL_##dr##_DIV; \ | 434 | reg &= ~BM_CLKCTRL_##dr##_DIV; \ |
406 | reg |= div << BP_CLKCTRL_##dr##_DIV; \ | 435 | reg |= div << BP_CLKCTRL_##dr##_DIV; \ |
407 | if (reg | (1 << clk->enable_shift)) { \ | 436 | if (reg & (1 << clk->enable_shift)) { \ |
408 | pr_err("%s: clock is gated\n", __func__); \ | 437 | pr_err("%s: clock is gated\n", __func__); \ |
409 | return -EINVAL; \ | 438 | return -EINVAL; \ |
410 | } \ | 439 | } \ |
@@ -640,6 +669,8 @@ static struct clk_lookup lookups[] = { | |||
640 | _REGISTER_CLOCK(NULL, "lradc", lradc_clk) | 669 | _REGISTER_CLOCK(NULL, "lradc", lradc_clk) |
641 | _REGISTER_CLOCK(NULL, "spdif", spdif_clk) | 670 | _REGISTER_CLOCK(NULL, "spdif", spdif_clk) |
642 | _REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk) | 671 | _REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk) |
672 | _REGISTER_CLOCK("mxs-saif.0", NULL, saif0_clk) | ||
673 | _REGISTER_CLOCK("mxs-saif.1", NULL, saif1_clk) | ||
643 | }; | 674 | }; |
644 | 675 | ||
645 | static int clk_misc_init(void) | 676 | static int clk_misc_init(void) |
@@ -708,11 +739,11 @@ static int clk_misc_init(void) | |||
708 | 739 | ||
709 | /* SAIF has to use frac div for functional operation */ | 740 | /* SAIF has to use frac div for functional operation */ |
710 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0); | 741 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0); |
711 | reg &= ~BM_CLKCTRL_SAIF0_DIV_FRAC_EN; | 742 | reg |= BM_CLKCTRL_SAIF0_DIV_FRAC_EN; |
712 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0); | 743 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0); |
713 | 744 | ||
714 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1); | 745 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1); |
715 | reg &= ~BM_CLKCTRL_SAIF1_DIV_FRAC_EN; | 746 | reg |= BM_CLKCTRL_SAIF1_DIV_FRAC_EN; |
716 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1); | 747 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1); |
717 | 748 | ||
718 | /* | 749 | /* |
@@ -738,11 +769,17 @@ static int clk_misc_init(void) | |||
738 | __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, | 769 | __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, |
739 | CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET); | 770 | CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET); |
740 | 771 | ||
741 | /* Extra fec clock setting */ | 772 | /* |
742 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET); | 773 | * Extra fec clock setting |
743 | reg &= ~BM_CLKCTRL_ENET_SLEEP; | 774 | * The DENX M28 uses an external clock source |
744 | reg |= BM_CLKCTRL_ENET_CLK_OUT_EN; | 775 | * and the clock output must not be enabled |
745 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET); | 776 | */ |
777 | if (!machine_is_m28evk()) { | ||
778 | reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET); | ||
779 | reg &= ~BM_CLKCTRL_ENET_SLEEP; | ||
780 | reg |= BM_CLKCTRL_ENET_CLK_OUT_EN; | ||
781 | __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET); | ||
782 | } | ||
746 | 783 | ||
747 | /* | 784 | /* |
748 | * 480 MHz seems too high to be ssp clock source directly, | 785 | * 480 MHz seems too high to be ssp clock source directly, |
@@ -767,13 +804,24 @@ int __init mx28_clocks_init(void) | |||
767 | clk_set_parent(&ssp0_clk, &ref_io0_clk); | 804 | clk_set_parent(&ssp0_clk, &ref_io0_clk); |
768 | clk_set_parent(&ssp1_clk, &ref_io0_clk); | 805 | clk_set_parent(&ssp1_clk, &ref_io0_clk); |
769 | 806 | ||
770 | clk_enable(&cpu_clk); | 807 | clk_prepare_enable(&cpu_clk); |
771 | clk_enable(&hbus_clk); | 808 | clk_prepare_enable(&hbus_clk); |
772 | clk_enable(&xbus_clk); | 809 | clk_prepare_enable(&xbus_clk); |
773 | clk_enable(&emi_clk); | 810 | clk_prepare_enable(&emi_clk); |
774 | clk_enable(&uart_clk); | 811 | clk_prepare_enable(&uart_clk); |
775 | 812 | ||
776 | clk_set_parent(&lcdif_clk, &ref_pix_clk); | 813 | clk_set_parent(&lcdif_clk, &ref_pix_clk); |
814 | clk_set_parent(&saif0_clk, &pll0_clk); | ||
815 | clk_set_parent(&saif1_clk, &pll0_clk); | ||
816 | |||
817 | /* | ||
818 | * Set an initial clock rate for the saif internal logic to work | ||
819 | * properly. This is important when working in EXTMASTER mode that | ||
820 | * uses the other saif's BITCLK&LRCLK but it still needs a basic | ||
821 | * clock which should be fast enough for the internal logic. | ||
822 | */ | ||
823 | clk_set_rate(&saif0_clk, 24000000); | ||
824 | clk_set_rate(&saif1_clk, 24000000); | ||
777 | 825 | ||
778 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 826 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); |
779 | 827 | ||