aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorEric Bénard <eric@eukrea.com>2010-10-11 11:59:47 -0400
committerSascha Hauer <s.hauer@pengutronix.de>2010-10-19 12:45:00 -0400
commit6a001b886c8c4ff7477a3692a2d87a9dbdd860ee (patch)
treeed794f6a7a3fc932854c874b48516870642dc64f /arch
parent217f580ba643eff91bac04a474a7db6d40863d5b (diff)
mx51: add resources for SD/MMC on i.MX51
the attached patch allows SD to work on i.MX51 with Wolfram's drivers Tested on i.MX51. Based on original patch from: Richard Zhu <r65037@freescale.com> Signed-off-by: Eric Bénard <eric@eukrea.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx5/clock-mx51.c104
-rw-r--r--arch/arm/mach-mx5/devices-imx51.h9
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 */
45static 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
44static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) 74static 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) \
791static unsigned long clk_##name##_get_rate(struct clk *clk) \ 835static 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) \
865static 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 */
821CLK_GET_RATE(uart, 1, UART) 896CLK_GET_RATE(uart, 1, UART)
822CLK_SET_PARENT(uart, 1, UART) 897CLK_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 */
926CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
927CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
928CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
929
930CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
931CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
932CLK_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,
935DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, 1019DEFINE_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 */
1023DEFINE_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);
1025DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
1026 clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
1027DEFINE_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);
1029DEFINE_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
973static void clk_tree_init(void) 1069static 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;
36extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst; 36extern 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)