diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-mx5/clock-mx51.c | 104 | ||||
-rw-r--r-- | arch/arm/mach-mx5/devices-imx51.h | 9 |
2 files changed, 113 insertions, 0 deletions
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index 9a39492c5b23..f2aae92cf0e2 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c | |||
@@ -41,6 +41,36 @@ static struct clk usboh3_clk; | |||
41 | 41 | ||
42 | #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ | 42 | #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ |
43 | 43 | ||
44 | /* calculate best pre and post dividers to get the required divider */ | ||
45 | static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post, | ||
46 | u32 max_pre, u32 max_post) | ||
47 | { | ||
48 | if (div >= max_pre * max_post) { | ||
49 | *pre = max_pre; | ||
50 | *post = max_post; | ||
51 | } else if (div >= max_pre) { | ||
52 | u32 min_pre, temp_pre, old_err, err; | ||
53 | min_pre = DIV_ROUND_UP(div, max_post); | ||
54 | old_err = max_pre; | ||
55 | for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) { | ||
56 | err = div % temp_pre; | ||
57 | if (err == 0) { | ||
58 | *pre = temp_pre; | ||
59 | break; | ||
60 | } | ||
61 | err = temp_pre - err; | ||
62 | if (err < old_err) { | ||
63 | old_err = err; | ||
64 | *pre = temp_pre; | ||
65 | } | ||
66 | } | ||
67 | *post = DIV_ROUND_UP(div, *pre); | ||
68 | } else { | ||
69 | *pre = div; | ||
70 | *post = 1; | ||
71 | } | ||
72 | } | ||
73 | |||
44 | static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) | 74 | static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) |
45 | { | 75 | { |
46 | u32 reg = __raw_readl(clk->enable_reg); | 76 | u32 reg = __raw_readl(clk->enable_reg); |
@@ -787,6 +817,20 @@ static struct clk emi_slow_clk = { | |||
787 | .secondary = s, \ | 817 | .secondary = s, \ |
788 | } | 818 | } |
789 | 819 | ||
820 | #define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \ | ||
821 | static struct clk name = { \ | ||
822 | .id = i, \ | ||
823 | .enable_reg = er, \ | ||
824 | .enable_shift = es, \ | ||
825 | .get_rate = pfx##_get_rate, \ | ||
826 | .set_rate = pfx##_set_rate, \ | ||
827 | .set_parent = pfx##_set_parent, \ | ||
828 | .enable = _clk_max_enable, \ | ||
829 | .disable = _clk_max_disable, \ | ||
830 | .parent = p, \ | ||
831 | .secondary = s, \ | ||
832 | } | ||
833 | |||
790 | #define CLK_GET_RATE(name, nr, bitsname) \ | 834 | #define CLK_GET_RATE(name, nr, bitsname) \ |
791 | static unsigned long clk_##name##_get_rate(struct clk *clk) \ | 835 | static unsigned long clk_##name##_get_rate(struct clk *clk) \ |
792 | { \ | 836 | { \ |
@@ -817,6 +861,37 @@ static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \ | |||
817 | return 0; \ | 861 | return 0; \ |
818 | } | 862 | } |
819 | 863 | ||
864 | #define CLK_SET_RATE(name, nr, bitsname) \ | ||
865 | static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \ | ||
866 | { \ | ||
867 | u32 reg, div, parent_rate; \ | ||
868 | u32 pre = 0, post = 0; \ | ||
869 | \ | ||
870 | parent_rate = clk_get_rate(clk->parent); \ | ||
871 | div = parent_rate / rate; \ | ||
872 | \ | ||
873 | if ((parent_rate / div) != rate) \ | ||
874 | return -EINVAL; \ | ||
875 | \ | ||
876 | __calc_pre_post_dividers(div, &pre, &post, \ | ||
877 | (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \ | ||
878 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \ | ||
879 | (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \ | ||
880 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\ | ||
881 | \ | ||
882 | /* Set sdhc1 clock divider */ \ | ||
883 | reg = __raw_readl(MXC_CCM_CSCDR##nr) & \ | ||
884 | ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \ | ||
885 | | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \ | ||
886 | reg |= (post - 1) << \ | ||
887 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ | ||
888 | reg |= (pre - 1) << \ | ||
889 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ | ||
890 | __raw_writel(reg, MXC_CCM_CSCDR##nr); \ | ||
891 | \ | ||
892 | return 0; \ | ||
893 | } | ||
894 | |||
820 | /* UART */ | 895 | /* UART */ |
821 | CLK_GET_RATE(uart, 1, UART) | 896 | CLK_GET_RATE(uart, 1, UART) |
822 | CLK_SET_PARENT(uart, 1, UART) | 897 | CLK_SET_PARENT(uart, 1, UART) |
@@ -847,6 +922,15 @@ static struct clk ecspi_main_clk = { | |||
847 | .set_parent = clk_ecspi_set_parent, | 922 | .set_parent = clk_ecspi_set_parent, |
848 | }; | 923 | }; |
849 | 924 | ||
925 | /* eSDHC */ | ||
926 | CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1) | ||
927 | CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1) | ||
928 | CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1) | ||
929 | |||
930 | CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2) | ||
931 | CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2) | ||
932 | CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2) | ||
933 | |||
850 | #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ | 934 | #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ |
851 | static struct clk name = { \ | 935 | static struct clk name = { \ |
852 | .id = i, \ | 936 | .id = i, \ |
@@ -935,6 +1019,16 @@ DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET, | |||
935 | DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, | 1019 | DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, |
936 | NULL, NULL, &ahb_clk, NULL); | 1020 | NULL, NULL, &ahb_clk, NULL); |
937 | 1021 | ||
1022 | /* eSDHC */ | ||
1023 | DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET, | ||
1024 | NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); | ||
1025 | DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET, | ||
1026 | clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk); | ||
1027 | DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET, | ||
1028 | NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); | ||
1029 | DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET, | ||
1030 | clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk); | ||
1031 | |||
938 | #define _REGISTER_CLOCK(d, n, c) \ | 1032 | #define _REGISTER_CLOCK(d, n, c) \ |
939 | { \ | 1033 | { \ |
940 | .dev_id = d, \ | 1034 | .dev_id = d, \ |
@@ -968,6 +1062,8 @@ static struct clk_lookup lookups[] = { | |||
968 | _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) | 1062 | _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) |
969 | _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) | 1063 | _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) |
970 | _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) | 1064 | _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) |
1065 | _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk) | ||
1066 | _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk) | ||
971 | }; | 1067 | }; |
972 | 1068 | ||
973 | static void clk_tree_init(void) | 1069 | static void clk_tree_init(void) |
@@ -1011,6 +1107,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, | |||
1011 | /* set the usboh3_clk parent to pll2_sw_clk */ | 1107 | /* set the usboh3_clk parent to pll2_sw_clk */ |
1012 | clk_set_parent(&usboh3_clk, &pll2_sw_clk); | 1108 | clk_set_parent(&usboh3_clk, &pll2_sw_clk); |
1013 | 1109 | ||
1110 | /* Set SDHC parents to be PLL2 */ | ||
1111 | clk_set_parent(&esdhc1_clk, &pll2_sw_clk); | ||
1112 | clk_set_parent(&esdhc2_clk, &pll2_sw_clk); | ||
1113 | |||
1114 | /* set SDHC root clock as 166.25MHZ*/ | ||
1115 | clk_set_rate(&esdhc1_clk, 166250000); | ||
1116 | clk_set_rate(&esdhc2_clk, 166250000); | ||
1117 | |||
1014 | /* System timer */ | 1118 | /* System timer */ |
1015 | mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), | 1119 | mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), |
1016 | MX51_MXC_INT_GPT); | 1120 | MX51_MXC_INT_GPT); |
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h index c233379256b8..547432d8420f 100644 --- a/arch/arm/mach-mx5/devices-imx51.h +++ b/arch/arm/mach-mx5/devices-imx51.h | |||
@@ -36,3 +36,12 @@ extern const struct imx_spi_imx_data imx51_cspi_data __initconst; | |||
36 | extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst; | 36 | extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst; |
37 | #define imx51_add_ecspi(id, pdata) \ | 37 | #define imx51_add_ecspi(id, pdata) \ |
38 | imx_add_spi_imx(&imx51_ecspi_data[id], pdata) | 38 | imx_add_spi_imx(&imx51_ecspi_data[id], pdata) |
39 | |||
40 | #define imx51_add_esdhc0(pdata) \ | ||
41 | imx_add_esdhc(0, MX51_MMC_SDHC1_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC1, pdata) | ||
42 | #define imx51_add_esdhc1(pdata) \ | ||
43 | imx_add_esdhc(1, MX51_MMC_SDHC2_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC2, pdata) | ||
44 | #define imx51_add_esdhc2(pdata) \ | ||
45 | imx_add_esdhc(2, MX51_MMC_SDHC3_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC3, pdata) | ||
46 | #define imx51_add_esdhc3(pdata) \ | ||
47 | imx_add_esdhc(3, MX51_MMC_SDHC4_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC4, pdata) | ||