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