SD/MMC for i.MX51
Shawn Guo
shawn.gsc at gmail.com
Mon Oct 18 08:13:48 UTC 2010
Correct Richard address ...
On Mon, Oct 18, 2010 at 4:10 PM, Shawn Guo <shawn.gsc at gmail.com> wrote:
> Hi Eric,
>
> Thanks for the links. I was following the patches to add the babbage
> registration specific bits (see patch below). I can see following mmc
> related boot log showing the card is initialized and recognized.
>
> sdhci: Copyright(c) Pierre Ossman
> mmc0: SDHCI controller on platform [sdhci-esdhc-imx.0] using DMA
> mmc1: SDHCI controller on platform [sdhci-esdhc-imx.1] using DMA
> ......
> Waiting for root device /dev/mmcblk0p3...
> mmc0: new high speed SD card at address fb74
> blk_queue_max_hw_sectors: set to minimum 8
> mmcblk0: mmc0:fb74 SD02G 1.83 GiB
> mmcblk0: p1 p2 p3
> ......
>
> But when I try to login console, it gives a bunch of error messages like below.
>
> mmcblk0: error -110 transferring data, sector 1737392, nr 2, card status 0xe00
> end_request: I/O error, dev mmcblk0, sector 1737392
> mmcblk0: error -84 transferring data, sector 1737394, nr 8, card status 0x900
> end_request: I/O error, dev mmcblk0, sector 1737394
> mmcblk0: error -84 transferring data, sector 1737402, nr 8, card status 0x900
> end_request: I/O error, dev mmcblk0, sector 1737402
> ......
>
> As you have tested Wolfram's bits on i.MX51 (eukrea?), probably my
> babbage registration bit is causing problem. Could you please help
> have a review to see if anything incorrect?
>
>
> On Mon, Oct 18, 2010 at 1:04 AM, Eric Bénard <eric at eukrea.com> wrote:
>> Hi Shawn,
>>
>> Le 17/10/2010 17:27, Shawn Guo a écrit :
>>>
>>> Thanks for the merging. But the bits for babbage mmc resources and
>>> driver registration are missing. I'm trying to add them for getting a
>>> bootable mmc linaro image, but running into some problem right now.
>>> Will continue digging tomorrow.
>>>
>> you can find a working example here :
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2010-October/028846.html
>>
>> before, you will need this patch serie :
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2010-October/028826.html
>> and this patch :
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2010-October/028855.html
>>
>> Eric
>>
>
>
> From 511b5ec7aaeb8c15b6613b9ff68e967998e6c37a Mon Sep 17 00:00:00 2001
> From: Shawn Guo <shawn.gsc at gmail.com>
> Date: Sun, 17 Oct 2010 22:31:34 +0800
> Subject: [PATCH] Add resource and registeration for wsa mmc driver
>
> Signed-off-by: Shawn Guo <shawn.gsc at gmail.com>
> ---
> arch/arm/mach-mx5/Kconfig | 1 +
> arch/arm/mach-mx5/board-mx51_babbage.c | 20 ++
> arch/arm/mach-mx5/clock-mx51.c | 268 +++++++++++++++--------
> arch/arm/mach-mx5/devices-imx51.h | 17 ++
> arch/arm/plat-mxc/devices/Kconfig | 3 +
> arch/arm/plat-mxc/devices/Makefile | 1 +
> arch/arm/plat-mxc/devices/platform-esdhc.c | 71 ++++++
> arch/arm/plat-mxc/include/mach/devices-common.h | 10 +
> arch/arm/plat-mxc/include/mach/esdhc.h | 16 ++
> arch/arm/plat-mxc/include/mach/iomux-mx51.h | 39 +++-
> arch/arm/plat-mxc/include/mach/mx51.h | 16 +-
> 11 files changed, 351 insertions(+), 111 deletions(-)
> create mode 100644 arch/arm/mach-mx5/devices-imx51.h
> create mode 100644 arch/arm/plat-mxc/devices/platform-esdhc.c
> create mode 100644 arch/arm/plat-mxc/include/mach/esdhc.h
>
> diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
> index 0848db5..a263666 100644
> --- a/arch/arm/mach-mx5/Kconfig
> +++ b/arch/arm/mach-mx5/Kconfig
> @@ -10,6 +10,7 @@ comment "MX5 platforms:"
>
> config MACH_MX51_BABBAGE
> bool "Support MX51 BABBAGE platforms"
> + select IMX_HAVE_PLATFORM_ESDHC
> help
> Include support for MX51 Babbage platform, also known as MX51EVK in
> u-boot. This includes specific configurations for the board and its
> diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c
> b/arch/arm/mach-mx5/board-mx51_babbage.c
> index 6e384d9..476bfe4 100644
> --- a/arch/arm/mach-mx5/board-mx51_babbage.c
> +++ b/arch/arm/mach-mx5/board-mx51_babbage.c
> @@ -31,6 +31,7 @@
> #include <asm/mach/arch.h>
> #include <asm/mach/time.h>
>
> +#include "devices-imx51.h"
> #include "devices.h"
>
> #define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */
> @@ -93,6 +94,22 @@ static struct pad_desc mx51babbage_pads[] = {
>
> /* USB HUB reset line*/
> MX51_PAD_GPIO_1_7__GPIO_1_7,
> +
> + /* SD 1 */
> + MX51_PAD_SD1_CMD__SD1_CMD,
> + MX51_PAD_SD1_CLK__SD1_CLK,
> + MX51_PAD_SD1_DATA0__SD1_DATA0,
> + MX51_PAD_SD1_DATA1__SD1_DATA1,
> + MX51_PAD_SD1_DATA2__SD1_DATA2,
> + MX51_PAD_SD1_DATA3__SD1_DATA3,
> +
> + /* SD 2 */
> + MX51_PAD_SD2_CMD__SD2_CMD,
> + MX51_PAD_SD2_CLK__SD2_CLK,
> + MX51_PAD_SD2_DATA0__SD2_DATA0,
> + MX51_PAD_SD2_DATA1__SD2_DATA1,
> + MX51_PAD_SD2_DATA2__SD2_DATA2,
> + MX51_PAD_SD2_DATA3__SD2_DATA3,
> };
>
> /* Serial ports */
> @@ -268,6 +285,9 @@ static void __init mxc_board_init(void)
> /* setback USBH1_STP to be function */
> mxc_iomux_v3_setup_pad(&usbh1stp);
> babbage_usbhub_reset();
> +
> + imx51_add_esdhc(0, NULL);
> + imx51_add_esdhc(1, NULL);
> }
>
> static void __init mx51_babbage_timer_init(void)
> diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
> index 57c10a9..c879a91 100644
> --- a/arch/arm/mach-mx5/clock-mx51.c
> +++ b/arch/arm/mach-mx5/clock-mx51.c
> @@ -41,34 +41,66 @@ static struct clk usboh3_clk;
>
> #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
>
> -static int _clk_ccgr_enable(struct clk *clk)
> +/* calculate best pre and post dividers to get the required divider */
> +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
> + u32 max_pre, u32 max_post)
> +{
> + if (div >= max_pre * max_post) {
> + *pre = max_pre;
> + *post = max_post;
> + } else if (div >= max_pre) {
> + u32 min_pre, temp_pre, old_err, err;
> + min_pre = DIV_ROUND_UP(div, max_post);
> + old_err = max_pre;
> + for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
> + err = div % temp_pre;
> + if (err == 0) {
> + *pre = temp_pre;
> + break;
> + }
> + err = temp_pre - err;
> + if (err < old_err) {
> + old_err = err;
> + *pre = temp_pre;
> + }
> + }
> + *post = DIV_ROUND_UP(div, *pre);
> + } else {
> + *pre = div;
> + *post = 1;
> + }
> +}
> +
> +static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
> {
> - u32 reg;
> + u32 reg = __raw_readl(clk->enable_reg);
> +
> + reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
> + reg |= mode << clk->enable_shift;
>
> - reg = __raw_readl(clk->enable_reg);
> - reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
> __raw_writel(reg, clk->enable_reg);
> +}
>
> +static int _clk_ccgr_enable(struct clk *clk)
> +{
> + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
> return 0;
> }
>
> static void _clk_ccgr_disable(struct clk *clk)
> {
> - u32 reg;
> - reg = __raw_readl(clk->enable_reg);
> - reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
> - __raw_writel(reg, clk->enable_reg);
> + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
> +}
>
> +static int _clk_ccgr_enable_inrun(struct clk *clk)
> +{
> + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
> + return 0;
> }
>
> static void _clk_ccgr_disable_inwait(struct clk *clk)
> {
> - u32 reg;
> -
> - reg = __raw_readl(clk->enable_reg);
> - reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
> - reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
> - __raw_writel(reg, clk->enable_reg);
> + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
> }
>
> /*
> @@ -542,64 +574,6 @@ static int _clk_ipg_per_set_parent(struct clk
> *clk, struct clk *parent)
> return 0;
> }
>
> -static unsigned long clk_uart_get_rate(struct clk *clk)
> -{
> - u32 reg, prediv, podf;
> - unsigned long parent_rate;
> -
> - parent_rate = clk_get_rate(clk->parent);
> -
> - reg = __raw_readl(MXC_CCM_CSCDR1);
> - prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
> - MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
> - podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
> - MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
> -
> - return parent_rate / (prediv * podf);
> -}
> -
> -static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
> -{
> - u32 reg, mux;
> -
> - mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
> - &lp_apm_clk);
> - reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
> - reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
> - __raw_writel(reg, MXC_CCM_CSCMR1);
> -
> - return 0;
> -}
> -
> -static unsigned long clk_usboh3_get_rate(struct clk *clk)
> -{
> - u32 reg, prediv, podf;
> - unsigned long parent_rate;
> -
> - parent_rate = clk_get_rate(clk->parent);
> -
> - reg = __raw_readl(MXC_CCM_CSCDR1);
> - prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
> - MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
> - podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
> - MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
> -
> - return parent_rate / (prediv * podf);
> -}
> -
> -static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
> -{
> - u32 reg, mux;
> -
> - mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
> - &lp_apm_clk);
> - reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
> - reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
> - __raw_writel(reg, MXC_CCM_CSCMR1);
> -
> - return 0;
> -}
> -
> static unsigned long get_high_reference_clock_rate(struct clk *clk)
> {
> return external_high_reference;
> @@ -715,18 +689,6 @@ static struct clk ipg_perclk = {
> .set_parent = _clk_ipg_per_set_parent,
> };
>
> -static struct clk uart_root_clk = {
> - .parent = &pll2_sw_clk,
> - .get_rate = clk_uart_get_rate,
> - .set_parent = _clk_uart_set_parent,
> -};
> -
> -static struct clk usboh3_clk = {
> - .parent = &pll2_sw_clk,
> - .get_rate = clk_usboh3_get_rate,
> - .set_parent = _clk_usboh3_set_parent,
> -};
> -
> static struct clk ahb_max_clk = {
> .parent = &ahb_clk,
> .enable_reg = MXC_CCM_CCGR0,
> @@ -762,21 +724,125 @@ static struct clk kpp_clk = {
> .id = 0,
> };
>
> -#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
> +#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
> static struct clk name = { \
> .id = i, \
> .enable_reg = er, \
> .enable_shift = es, \
> - .get_rate = gr, \
> - .set_rate = sr, \
> - .enable = _clk_ccgr_enable, \
> - .disable = _clk_ccgr_disable, \
> + .get_rate = pfx##_get_rate, \
> + .set_rate = pfx##_set_rate, \
> + .set_parent = pfx##_set_parent, \
> + .enable = _clk_max_enable, \
> + .disable = _clk_max_disable, \
> .parent = p, \
> .secondary = s, \
> }
>
> -/* DEFINE_CLOCK(name, id, enable_reg, enable_shift,
> - get_rate, set_rate, parent, secondary); */
> +#define CLK_GET_RATE(name, nr, bitsname) \
> +static unsigned long clk_##name##_get_rate(struct clk *clk) \
> +{ \
> + u32 reg, pred, podf; \
> + \
> + reg = __raw_readl(MXC_CCM_CSCDR##nr); \
> + pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
> + >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
> + podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
> + >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
> + \
> + return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
> + (pred + 1) * (podf + 1)); \
> +}
> +
> +#define CLK_SET_PARENT(name, nr, bitsname) \
> +static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
> +{ \
> + u32 reg, mux; \
> + \
> + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
> + &pll3_sw_clk, &lp_apm_clk); \
> + reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
> + ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
> + reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
> + __raw_writel(reg, MXC_CCM_CSCMR##nr); \
> + \
> + return 0; \
> +}
> +
> +#define CLK_SET_RATE(name, nr, bitsname) \
> +static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
> +{ \
> + u32 reg, div, parent_rate; \
> + u32 pre = 0, post = 0; \
> + \
> + parent_rate = clk_get_rate(clk->parent); \
> + div = parent_rate / rate; \
> + \
> + if ((parent_rate / div) != rate) \
> + return -EINVAL; \
> + \
> + __calc_pre_post_dividers(div, &pre, &post, \
> + (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
> + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
> + (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
> + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
> + \
> + /* Set sdhc1 clock divider */ \
> + reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
> + ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
> + | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
> + reg |= (post - 1) << \
> + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
> + reg |= (pre - 1) << \
> + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
> + __raw_writel(reg, MXC_CCM_CSCDR##nr); \
> + \
> + return 0; \
> +}
> +
> +/* UART */
> +CLK_GET_RATE(uart, 1, UART)
> +CLK_SET_PARENT(uart, 1, UART)
> +
> +static struct clk uart_root_clk = {
> + .parent = &pll2_sw_clk,
> + .get_rate = clk_uart_get_rate,
> + .set_parent = clk_uart_set_parent,
> +};
> +
> +/* USBOH3 */
> +CLK_GET_RATE(usboh3, 1, USBOH3)
> +CLK_SET_PARENT(usboh3, 1, USBOH3)
> +
> +static struct clk usboh3_clk = {
> + .parent = &pll2_sw_clk,
> + .get_rate = clk_usboh3_get_rate,
> + .set_parent = clk_usboh3_set_parent,
> +};
> +
> +/* eSDHC */
> +CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
> +CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
> +CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
> +
> +CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
> +CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
> +CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
> +
> +#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
> + static struct clk name = { \
> + .id = i, \
> + .enable_reg = er, \
> + .enable_shift = es, \
> + .get_rate = gr, \
> + .set_rate = sr, \
> + .enable = e, \
> + .disable = d, \
> + .parent = p, \
> + .secondary = s, \
> + }
> +
> +#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
> + DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable,
> _clk_ccgr_disable, p, s)
>
> /* Shared peripheral bus arbiter */
> DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
> @@ -814,6 +880,16 @@ DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1,
> MXC_CCM_CCGRx_CG11_OFFSET,
> DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
> NULL, NULL, &ipg_clk, NULL);
>
> +/* eSDHC */
> +DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
> + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
> +DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
> + clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
> +DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
> + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
> +DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
> + clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
> +
> #define _REGISTER_CLOCK(d, n, c) \
> { \
> .dev_id = d, \
> @@ -837,6 +913,8 @@ static struct clk_lookup lookups[] = {
> _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
> _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
> _REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
> + _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
> + _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
> };
>
> static void clk_tree_init(void)
> @@ -880,6 +958,14 @@ int __init mx51_clocks_init(unsigned long ckil,
> unsigned long osc,
> /* set the usboh3_clk parent to pll2_sw_clk */
> clk_set_parent(&usboh3_clk, &pll2_sw_clk);
>
> + /* Set SDHC parents to be PLL2 */
> + clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
> + clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
> +
> + /* set SDHC root clock as 166.25MHZ*/
> + clk_set_rate(&esdhc1_clk, 166250000);
> + clk_set_rate(&esdhc2_clk, 166250000);
> +
> /* System timer */
> mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
> MX51_MXC_INT_GPT);
> diff --git a/arch/arm/mach-mx5/devices-imx51.h
> b/arch/arm/mach-mx5/devices-imx51.h
> new file mode 100644
> index 0000000..1c43940
> --- /dev/null
> +++ b/arch/arm/mach-mx5/devices-imx51.h
> @@ -0,0 +1,17 @@
> +/*
>
> + * Copyright (C) 2010 Jason Wang <jason77.wang at gmail.com>
>
> + *
>
> + * based on mach-mx3/devices-imx35.h which is
>
> + * Copyright (C) 2010 Pengutronix
>
> + * Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
>
> + *
>
> + * This program is free software; you can redistribute it and/or
> modify it under
>
> + * the terms of the GNU General Public License version 2 as published by the
>
> + * Free Software Foundation.
>
> + */
>
> +#include <mach/mx51.h>
>
> +#include <mach/devices-common.h>
>
> +
>
> +extern const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst;
>
> +#define imx51_add_esdhc(id, pdata) \
>
> + imx_add_esdhc(&imx51_esdhc_data[id], pdata)
>
> diff --git a/arch/arm/plat-mxc/devices/Kconfig
> b/arch/arm/plat-mxc/devices/Kconfig
> index 9ab784b..4730d2c 100644
> --- a/arch/arm/plat-mxc/devices/Kconfig
> +++ b/arch/arm/plat-mxc/devices/Kconfig
> @@ -13,3 +13,6 @@ config IMX_HAVE_PLATFORM_MXC_NAND
>
> config IMX_HAVE_PLATFORM_SPI_IMX
> bool
> +
> +config IMX_HAVE_PLATFORM_ESDHC
> + bool
> diff --git a/arch/arm/plat-mxc/devices/Makefile
> b/arch/arm/plat-mxc/devices/Makefile
> index 347da51..81aa17e 100644
> --- a/arch/arm/plat-mxc/devices/Makefile
> +++ b/arch/arm/plat-mxc/devices/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
> obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
> obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
> obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) += platform-spi_imx.o
> +obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o
> diff --git a/arch/arm/plat-mxc/devices/platform-esdhc.c
> b/arch/arm/plat-mxc/devices/platform-esdhc.c
> new file mode 100644
> index 0000000..668050b
> --- /dev/null
> +++ b/arch/arm/plat-mxc/devices/platform-esdhc.c
> @@ -0,0 +1,71 @@
> +/*
> + * Copyright (C) 2010 Pengutronix, Wolfram Sang <w.sang at pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or
> modify it under
> + * the terms of the GNU General Public License version 2 as published by the
> + * Free Software Foundation.
> + */
> +
> +#include <mach/hardware.h>
> +#include <mach/devices-common.h>
> +#include <mach/esdhc.h>
> +
> +#define imx_esdhc_imx_data_entry_single(soc, _id, hwid) \
> + { \
> + .id = _id, \
> + .iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR, \
> + .irq = soc ## _INT_ESDHC ## hwid, \
> + }
> +
> +#define imx_esdhc_imx_data_entry(soc, id, hwid) \
> + [id] = imx_esdhc_imx_data_entry_single(soc, id, hwid)
> +
> +#ifdef CONFIG_ARCH_MX25
> +const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst = {
> +#define imx25_esdhc_data_entry(_id, _hwid) \
> + imx_esdhc_imx_data_entry(MX25, _id, _hwid)
> + imx25_esdhc_data_entry(0, 1),
> + imx25_esdhc_data_entry(1, 2),
> +};
> +#endif /* ifdef CONFIG_ARCH_MX25 */
> +
> +#ifdef CONFIG_ARCH_MX35
> +const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst = {
> +#define imx35_esdhc_data_entry(_id, _hwid) \
> + imx_esdhc_imx_data_entry(MX35, _id, _hwid)
> + imx35_esdhc_data_entry(0, 1),
> + imx35_esdhc_data_entry(1, 2),
> + imx35_esdhc_data_entry(2, 3),
> +};
> +#endif /* ifdef CONFIG_ARCH_MX35 */
> +
> +#ifdef CONFIG_ARCH_MX51
> +const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst = {
> +#define imx51_esdhc_data_entry(_id, _hwid) \
> + imx_esdhc_imx_data_entry(MX51, _id, _hwid)
> + imx51_esdhc_data_entry(0, 1),
> + imx51_esdhc_data_entry(1, 2),
> + imx51_esdhc_data_entry(2, 3),
> + imx51_esdhc_data_entry(3, 4),
> +};
> +#endif /* ifdef CONFIG_ARCH_MX51 */
> +
> +struct platform_device *__init imx_add_esdhc(
> + const struct imx_esdhc_imx_data *data,
> + const struct esdhc_platform_data *pdata)
> +{
> + struct resource res[] = {
> + {
> + .start = data->iobase,
> + .end = data->iobase + SZ_16K - 1,
> + .flags = IORESOURCE_MEM,
> + }, {
> + .start = data->irq,
> + .end = data->irq,
> + .flags = IORESOURCE_IRQ,
> + },
> + };
> +
> + return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
> + ARRAY_SIZE(res), pdata, sizeof(*pdata));
> +}
> diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h
> b/arch/arm/plat-mxc/include/mach/devices-common.h
> index c5f68c5..af7a232 100644
> --- a/arch/arm/plat-mxc/include/mach/devices-common.h
> +++ b/arch/arm/plat-mxc/include/mach/devices-common.h
> @@ -58,3 +58,13 @@ struct platform_device *__init
> imx_add_mxc_nand_v21(resource_size_t iobase,
> struct platform_device *__init imx_add_spi_imx(int id,
> resource_size_t iobase, resource_size_t iosize, int irq,
> const struct spi_imx_master *pdata);
> +
> +#include <mach/esdhc.h>
> +struct imx_esdhc_imx_data {
> + int id;
> + resource_size_t iobase;
> + resource_size_t irq;
> +};
> +struct platform_device *__init imx_add_esdhc(
> + const struct imx_esdhc_imx_data *data,
> + const struct esdhc_platform_data *pdata);
> diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h
> b/arch/arm/plat-mxc/include/mach/esdhc.h
> new file mode 100644
> index 0000000..0724bcd
> --- /dev/null
> +++ b/arch/arm/plat-mxc/include/mach/esdhc.h
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright 2010 Wolfram Sang <w.sang at pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; version 2
> + * of the License.
> + */
> +
> +#ifndef __ASM_ARCH_IMX_ESDHC_H
> +#define __ASM_ARCH_IMX_ESDHC_H
> +
> +struct esdhc_platform_data {
> + unsigned int wp_gpio; /* write protect pin */
> +};
> +#endif /* __ASM_ARCH_IMX_ESDHC_H */
> diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
> b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
> index 21bfa46..935f790 100644
> --- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
> +++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
> @@ -45,6 +45,9 @@ typedef enum iomux_config {
> PAD_CTL_PKE | PAD_CTL_HYS)
> #define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \
> PAD_CTL_SRE_FAST)
> +#define MX51_SDHCI_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
> + PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
> + PAD_CTL_DVS)
>
> /*
> * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
> @@ -294,20 +297,32 @@ typedef enum iomux_config {
> #define MX51_PAD_DISP2_DAT13__DISP2_DAT13 IOMUX_PAD(0x790,
> 0x388, 0, 0x0, 0, NO_PAD_CTRL)
> #define MX51_PAD_DISP2_DAT14__DISP2_DAT14 IOMUX_PAD(0x794,
> 0x38C, 0, 0x0, 0, NO_PAD_CTRL)
> #define MX51_PAD_DISP2_DAT15__DISP2_DAT15 IOMUX_PAD(0x798,
> 0x390, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79C,
> 0x394, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7A0,
> 0x398, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7A4,
> 0x39C, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7A8,
> 0x3A0, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7AC,
> 0x3A4, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7B0,
> 0x3A8, 0, 0x0, 0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79C, 0x394,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7A0, 0x398,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
> +#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7A4, 0x39C,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7A8, 0x3A0,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7AC, 0x3A4,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7B0, 0x3A8,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> #define MX51_PAD_GPIO_1_0__GPIO_1_0 IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,
> 0, NO_PAD_CTRL)
> #define MX51_PAD_GPIO_1_1__GPIO_1_1 IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,
> 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7BC,
> 0x3B4, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7C0,
> 0x3B8, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7C4,
> 0x3BC, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7C8,
> 0x3C0, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7CC,
> 0x3C4, 0, 0x0, 0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7D0,
> 0x3C8, 0, 0x0, 0, NO_PAD_CTRL)
> +#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7BC, 0x3B4,
> IOMUX_CONFIG_SION, 0x0, 1, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7C0, 0x3B8,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
> +#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7C4, 0x3BC,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7C8, 0x3C0,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7CC, 0x3C4,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7D0, 0x3C8,
> IOMUX_CONFIG_SION, 0x0, 0, \
> + MX51_SDHCI_PAD_CTRL)
> #define MX51_PAD_GPIO_1_2__GPIO_1_2 IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0,
> 0, NO_PAD_CTRL)
> #define MX51_PAD_GPIO_1_2__I2C2_SCL IOMUX_PAD(0x7D4, 0x3CC, (2 |
> IOMUX_CONFIG_SION), \
> 0x9b8, 3, MX51_I2C_PAD_CTRL)
> diff --git a/arch/arm/plat-mxc/include/mach/mx51.h
> b/arch/arm/plat-mxc/include/mach/mx51.h
> index 5aad344..5be17ae 100644
> --- a/arch/arm/plat-mxc/include/mach/mx51.h
> +++ b/arch/arm/plat-mxc/include/mach/mx51.h
> @@ -76,13 +76,13 @@
> #define MX51_SPBA0_BASE_ADDR_VIRT 0xFB100000
> #define MX51_SPBA0_SIZE SZ_1M
>
> -#define MX51_MMC_SDHC1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00004000)
> -#define MX51_MMC_SDHC2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00008000)
> +#define MX51_ESDHC1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00004000)
> +#define MX51_ESDHC2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00008000)
> #define MX51_UART3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x0000C000)
> #define MX51_CSPI1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00010000)
> #define MX51_SSI2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00014000)
> -#define MX51_MMC_SDHC3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00020000)
> -#define MX51_MMC_SDHC4_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00024000)
> +#define MX51_ESDHC3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00020000)
> +#define MX51_ESDHC4_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00024000)
> #define MX51_SPDIF_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00028000)
> #define MX51_ATA_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00030000)
> #define MX51_SLIM_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00034000)
> @@ -319,10 +319,10 @@
> */
> #define MX51_MXC_INT_BASE 0
> #define MX51_MXC_INT_RESV0 0
> -#define MX51_MXC_INT_MMC_SDHC1 1
> -#define MX51_MXC_INT_MMC_SDHC2 2
> -#define MX51_MXC_INT_MMC_SDHC3 3
> -#define MX51_MXC_INT_MMC_SDHC4 4
> +#define MX51_INT_ESDHC1 1
> +#define MX51_INT_ESDHC2 2
> +#define MX51_INT_ESDHC3 3
> +#define MX51_INT_ESDHC4 4
> #define MX51_MXC_INT_RESV5 5
> #define MX51_MXC_INT_SDMA 6
> #define MX51_MXC_INT_IOMUX 7
> --
> 1.7.1
>
>
> --
> Regards,
> Shawn
>
--
Regards,
Shawn
More information about the linaro-dev
mailing list