Hi Marek,

On 08/29/11 01:02, Marek Vasut wrote:
> Signed-off-by: Marek Vasut <marek.va...@gmail.com>
> ---
>  arch/arm/include/asm/arch-pxa/regs-mmc.h |  155 +++++++++++
>  drivers/mmc/Makefile                     |    1 +
>  drivers/mmc/pxa_mmc_gen.c                |  442 
> ++++++++++++++++++++++++++++++
>  3 files changed, 598 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-pxa/regs-mmc.h
>  create mode 100644 drivers/mmc/pxa_mmc_gen.c
> 
> diff --git a/arch/arm/include/asm/arch-pxa/regs-mmc.h 
> b/arch/arm/include/asm/arch-pxa/regs-mmc.h
> new file mode 100644
> index 0000000..fd1eb1e
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-pxa/regs-mmc.h
> @@ -0,0 +1,155 @@
> +/*
> + * Copyright (C) 2011 Marek Vasut <marek.va...@gmail.com>
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef      __REGS_MMC_H__
> +#define      __REGS_MMC_H__
> +
> +#define      MMC0_BASE       0x41100000
> +#define      MMC1_BASE       0x42000000
> +
> +int pxa_mmc_register(int card_index);
> +
> +struct pxa_mmc_regs {
> +     uint32_t        strpcl;
> +     uint32_t        stat;
> +     uint32_t        clkrt;
> +     uint32_t        spi;
> +     uint32_t        cmdat;
> +     uint32_t        resto;
> +     uint32_t        rdto;
> +     uint32_t        blklen;
> +     uint32_t        nob;
> +     uint32_t        prtbuf;
> +     uint32_t        i_mask;
> +     uint32_t        i_reg;
> +     uint32_t        cmd;
> +     uint32_t        argh;
> +     uint32_t        argl;
> +     uint32_t        res;
> +     uint32_t        rxfifo;
> +     uint32_t        txfifo;

Isn't space would be enough?
I mean, they all the same type, so no alignment issues...

> +};
> +
> +/* MMC_STRPCL */
> +#define      MMC_STRPCL_STOP_CLK             (1 << 0)
> +#define      MMC_STRPCL_START_CLK            (1 << 1)
> +
> +/* MMC_STAT */
> +#define      MMC_STAT_END_CMD_RES            (1 << 13)
> +#define      MMC_STAT_PRG_DONE               (1 << 12)
> +#define      MMC_STAT_DATA_TRAN_DONE         (1 << 11)
> +#define      MMC_STAT_CLK_EN                 (1 << 8)
> +#define      MMC_STAT_RECV_FIFO_FULL         (1 << 7)
> +#define      MMC_STAT_XMIT_FIFO_EMPTY        (1 << 6)
> +#define      MMC_STAT_RES_CRC_ERROR          (1 << 5)
> +#define      MMC_STAT_SPI_READ_ERROR_TOKEN   (1 << 4)
> +#define      MMC_STAT_CRC_READ_ERROR         (1 << 3)
> +#define      MMC_STAT_CRC_WRITE_ERROR        (1 << 2)
> +#define      MMC_STAT_TIME_OUT_RESPONSE      (1 << 1)
> +#define      MMC_STAT_READ_TIME_OUT          (1 << 0)
> +
> +/* MMC_CLKRT */
> +#define      MMC_CLKRT_20MHZ                 0
> +#define      MMC_CLKRT_10MHZ                 1
> +#define      MMC_CLKRT_5MHZ                  2
> +#define      MMC_CLKRT_2_5MHZ                3
> +#define      MMC_CLKRT_1_25MHZ               4
> +#define      MMC_CLKRT_0_625MHZ              5
> +#define      MMC_CLKRT_0_3125MHZ             6
> +
> +/* MMC_SPI */
> +#define      MMC_SPI_EN                      (1 << 0)
> +#define      MMC_SPI_CS_EN                   (1 << 2)
> +#define      MMC_SPI_CS_ADDRESS              (1 << 3)
> +#define      MMC_SPI_CRC_ON                  (1 << 1)
> +
> +/* MMC_CMDAT */
> +#define      MMC_CMDAT_SD_4DAT               (1 << 8)
> +#define      MMC_CMDAT_MMC_DMA_EN            (1 << 7)
> +#define      MMC_CMDAT_INIT                  (1 << 6)
> +#define      MMC_CMDAT_BUSY                  (1 << 5)
> +#define      MMC_CMDAT_BCR                   (MMC_CMDAT_BUSY | 
> MMC_CMDAT_INIT)
> +#define      MMC_CMDAT_STREAM                (1 << 4)
> +#define      MMC_CMDAT_WRITE                 (1 << 3)
> +#define      MMC_CMDAT_DATA_EN               (1 << 2)
> +#define      MMC_CMDAT_R0                    0
> +#define      MMC_CMDAT_R1                    1
> +#define      MMC_CMDAT_R2                    2
> +#define      MMC_CMDAT_R3                    3
> +
> +/* MMC_RESTO */
> +#define      MMC_RES_TO_MAX_MASK             0x7f
> +
> +/* MMC_RDTO */
> +#define      MMC_READ_TO_MAX_MASK            0xffff
> +
> +/* MMC_BLKLEN */
> +#define      MMC_BLK_LEN_MAX_MASK            0x3ff
> +
> +/* MMC_PRTBUF */
> +#define      MMC_PRTBUF_BUF_PART_FULL        (1 << 0)
> +
> +/* MMC_I_MASK */
> +#define      MMC_I_MASK_TXFIFO_WR_REQ        (1 << 6)
> +#define      MMC_I_MASK_RXFIFO_RD_REQ        (1 << 5)
> +#define      MMC_I_MASK_CLK_IS_OFF           (1 << 4)
> +#define      MMC_I_MASK_STOP_CMD             (1 << 3)
> +#define      MMC_I_MASK_END_CMD_RES          (1 << 2)
> +#define      MMC_I_MASK_PRG_DONE             (1 << 1)
> +#define      MMC_I_MASK_DATA_TRAN_DONE       (1 << 0)
> +#define      MMC_I_MASK_ALL                  0x7f
> +
> +
> +/* MMC_I_REG */
> +#define      MMC_I_REG_TXFIFO_WR_REQ         (1 << 6)
> +#define      MMC_I_REG_RXFIFO_RD_REQ         (1 << 5)
> +#define      MMC_I_REG_CLK_IS_OFF            (1 << 4)
> +#define      MMC_I_REG_STOP_CMD              (1 << 3)
> +#define      MMC_I_REG_END_CMD_RES           (1 << 2)
> +#define      MMC_I_REG_PRG_DONE              (1 << 1)
> +#define      MMC_I_REG_DATA_TRAN_DONE        (1 << 0)
> +
> +/* MMC_CMD */
> +#define      MMC_CMD_INDEX_MAX               0x6f
> +#define      CMD(x)  (x)

You've missed this one

> +
> +#define      MMC_R1_IDLE_STATE               0x01
> +#define      MMC_R1_ERASE_STATE              0x02
> +#define      MMC_R1_ILLEGAL_CMD              0x04
> +#define      MMC_R1_COM_CRC_ERR              0x08
> +#define      MMC_R1_ERASE_SEQ_ERR            0x01
> +#define      MMC_R1_ADDR_ERR                 0x02
> +#define      MMC_R1_PARAM_ERR                0x04
> +
> +#define      MMC_R1B_WP_ERASE_SKIP           0x0002
> +#define      MMC_R1B_ERR                     0x0004
> +#define      MMC_R1B_CC_ERR                  0x0008
> +#define      MMC_R1B_CARD_ECC_ERR            0x0010
> +#define      MMC_R1B_WP_VIOLATION            0x0020
> +#define      MMC_R1B_ERASE_PARAM             0x0040
> +#define      MMC_R1B_OOR                     0x0080
> +#define      MMC_R1B_IDLE_STATE              0x0100
> +#define      MMC_R1B_ERASE_RESET             0x0200
> +#define      MMC_R1B_ILLEGAL_CMD             0x0400
> +#define      MMC_R1B_COM_CRC_ERR             0x0800
> +#define      MMC_R1B_ERASE_SEQ_ERR           0x1000
> +#define      MMC_R1B_ADDR_ERR                0x2000
> +#define      MMC_R1B_PARAM_ERR               0x4000

All the above defines are really unnecessarily "tabbed"...
The values are fine, but why the names?

> +
> +#endif       /* __REGS_MMC_H__ */
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 3968c14..59bda49 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -38,6 +38,7 @@ COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o
>  COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o
>  COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
>  COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o
> +COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
>  COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o
>  COBJS-$(CONFIG_SDHCI) += sdhci.o
>  COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
> diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
> new file mode 100644
> index 0000000..aa475e5
> --- /dev/null
> +++ b/drivers/mmc/pxa_mmc_gen.c
> @@ -0,0 +1,442 @@
> +/*
> + * Copyright (C) 2010 Marek Vasut <marek.va...@gmail.com>
> + *
> + * Loosely based on the old code and Linux's PXA MMC driver
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <malloc.h>
> +
> +#include <mmc.h>
> +#include <asm/errno.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/arch/regs-mmc.h>
> +#include <asm/io.h>
> +
> +/* PXAMMC Generic default config for various CPUs */
> +#if defined(CONFIG_PXA250)
> +#define      PXAMMC_FIFO_SIZE        1
> +#define      PXAMMC_MIN_SPEED        312500
> +#define      PXAMMC_MAX_SPEED        20000000
> +#define      PXAMMC_HOST_CAPS        (0)
> +#elif defined(CONFIG_PXA27X)
> +#define      PXAMMC_CRC_SKIP
> +#define      PXAMMC_FIFO_SIZE        32
> +#define      PXAMMC_MIN_SPEED        304000
> +#define      PXAMMC_MAX_SPEED        19500000
> +#define      PXAMMC_HOST_CAPS        (MMC_MODE_4BIT)
> +#elif defined(CONFIG_CPU_MONAHANS)
> +#define      PXAMMC_FIFO_SIZE        32
> +#define      PXAMMC_MIN_SPEED        304000
> +#define      PXAMMC_MAX_SPEED        26000000
> +#define      PXAMMC_HOST_CAPS        (MMC_MODE_4BIT | MMC_MODE_HS)

Same here... and below... why?

> +#else
> +#error "This CPU isn't supported by PXA MMC!"
> +#endif
> +
> +#define      MMC_STAT_ERRORS                                                 
> \
> +     (MMC_STAT_RES_CRC_ERROR | MMC_STAT_SPI_READ_ERROR_TOKEN |       \
> +     MMC_STAT_CRC_READ_ERROR | MMC_STAT_TIME_OUT_RESPONSE |          \
> +     MMC_STAT_READ_TIME_OUT | MMC_STAT_CRC_WRITE_ERROR)
> +
> +/* 1 millisecond (in wait cycles below it's 100 x 10uS waits) */
> +#define      PXA_MMC_TIMEOUT 100
> +
> +struct pxa_mmc_priv {
> +     struct pxa_mmc_regs *regs;
> +};
> +
> +/* Wait for bit to be set */
> +static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     unsigned int timeout = PXA_MMC_TIMEOUT;
> +
> +     /* Wait for bit to be set */
> +     while (--timeout) {
> +             if (readl(&regs->stat) & mask)
> +                     break;
> +             udelay(10);
> +     }
> +
> +     if (!timeout)
> +             return -ETIMEDOUT;
> +
> +     return 0;
> +}
> +
> +static int pxa_mmc_stop_clock(struct mmc *mmc)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     unsigned int timeout = PXA_MMC_TIMEOUT;
> +
> +     /* If the clock aren't running, exit */
> +     if (!(readl(&regs->stat) & MMC_STAT_CLK_EN))
> +             return 0;
> +
> +     /* Tell the controller to turn off the clock */
> +     writel(MMC_STRPCL_STOP_CLK, &regs->strpcl);
> +
> +     /* Wait until the clock are off */
> +     while (--timeout) {
> +             if (!(readl(&regs->stat) & MMC_STAT_CLK_EN))
> +                     break;
> +             udelay(10);
> +     }
> +
> +     /* The clock refused to stop, scream and die a painful death */
> +     if (!timeout)
> +             return -ETIMEDOUT;
> +
> +     /* The clock stopped correctly */
> +     return 0;
> +}
> +
> +static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> +                             uint32_t cmdat)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     int ret;
> +
> +     /* The card can send a "busy" response */
> +     if (cmd->flags & MMC_RSP_BUSY)
> +             cmdat |= MMC_CMDAT_BUSY;
> +
> +     /* Inform the controller about response type */
> +     switch (cmd->resp_type) {
> +     case MMC_RSP_R1:
> +     case MMC_RSP_R1b:
> +             cmdat |= MMC_CMDAT_R1;
> +             break;
> +     case MMC_RSP_R2:
> +             cmdat |= MMC_CMDAT_R2;
> +             break;
> +     case MMC_RSP_R3:
> +             cmdat |= MMC_CMDAT_R3;
> +             break;
> +     default:
> +             break;
> +     }
> +
> +     /* Load command and it's arguments into the controller */
> +     writel(cmd->cmdidx, &regs->cmd);
> +     writel(cmd->cmdarg >> 16, &regs->argh);
> +     writel(cmd->cmdarg & 0xffff, &regs->argl);
> +     writel(cmdat, &regs->cmdat);
> +
> +     /* Start the controller clock and wait until they are started */
> +     writel(MMC_STRPCL_START_CLK, &regs->strpcl);
> +
> +     ret = pxa_mmc_wait(mmc, MMC_STAT_CLK_EN);
> +     if (ret)
> +             return ret;
> +
> +     /* Correct and happy end */
> +     return 0;
> +}
> +
> +static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     uint32_t a, b, c;
> +     int i;
> +     int stat;
> +
> +     /* Read the controller status */
> +     stat = readl(&regs->stat);
> +
> +     /*
> +      * Linux says:
> +      * Did I mention this is Sick.  We always need to
> +      * discard the upper 8 bits of the first 16-bit word.
> +      */
> +     a = readl(&regs->res) & 0xffff;
> +     for (i = 0; i < 4; i++) {
> +             b = readl(&regs->res) & 0xffff;
> +             c = readl(&regs->res) & 0xffff;
> +             cmd->response[i] = (a << 24) | (b << 8) | (c >> 8);
> +             a = c;
> +     }
> +
> +     /* The command response didn't arrive */
> +     if (stat & MMC_STAT_TIME_OUT_RESPONSE)
> +             return -ETIMEDOUT;
> +     else if (stat & MMC_STAT_RES_CRC_ERROR && cmd->flags & MMC_RSP_CRC) {
> +#ifdef       PXAMMC_CRC_SKIP
> +             if (cmd->flags & MMC_RSP_136 && cmd->response[0] & (1 << 31))
> +                     printf("Ignoring CRC, this may be dangerous!\n");
> +             else
> +#endif
> +             return -EILSEQ;
> +     }
> +
> +     /* The command response was successfully read */
> +     return 0;
> +}
> +
> +static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     uint32_t len;
> +     uint32_t *buf = (uint32_t *)data->dest;
> +     int size;
> +     int ret;
> +
> +     len = data->blocks * data->blocksize;
> +
> +     while (len) {
> +             /* The controller has data ready */
> +             if (readl(&regs->i_reg) & MMC_I_REG_RXFIFO_RD_REQ) {
> +                     size = min(len, PXAMMC_FIFO_SIZE);
> +                     len -= size;
> +                     size /= 4;
> +
> +                     /* Read data into the buffer */
> +                     while (size--)
> +                             *buf++ = readl(&regs->rxfifo);
> +
> +             }
> +
> +             if (readl(&regs->stat) & MMC_STAT_ERRORS)
> +                     return -EIO;
> +     }
> +
> +     /* Wait for the transmission-done interrupt */
> +     ret = pxa_mmc_wait(mmc, MMC_STAT_DATA_TRAN_DONE);
> +     if (ret)
> +             return ret;
> +
> +     return 0;
> +}
> +
> +static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     uint32_t len;
> +     uint32_t *buf = (uint32_t *)data->src;
> +     int size;
> +     int ret;
> +
> +     len = data->blocks * data->blocksize;
> +
> +     while (len) {
> +             /* The controller is ready to receive data */
> +             if (readl(&regs->i_reg) & MMC_I_REG_TXFIFO_WR_REQ) {
> +                     size = min(len, PXAMMC_FIFO_SIZE);
> +                     len -= size;
> +                     size /= 4;
> +
> +                     while (size--)
> +                             writel(*buf++, &regs->txfifo);
> +
> +                     if (min(len, PXAMMC_FIFO_SIZE) < 32)
> +                             writel(MMC_PRTBUF_BUF_PART_FULL, &regs->prtbuf);
> +             }
> +
> +             if (readl(&regs->stat) & MMC_STAT_ERRORS)
> +                     return -EIO;
> +     }
> +
> +     /* Wait for the transmission-done interrupt */
> +     ret = pxa_mmc_wait(mmc, MMC_STAT_DATA_TRAN_DONE);
> +     if (ret)
> +             return ret;
> +
> +     /* Wait until the data are really written to the card */
> +     ret = pxa_mmc_wait(mmc, MMC_STAT_PRG_DONE);
> +     if (ret)
> +             return ret;
> +
> +     return 0;
> +}
> +
> +static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
> +                             struct mmc_data *data)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     uint32_t cmdat = 0;
> +     int ret;
> +
> +     /* Stop the controller */
> +     ret = pxa_mmc_stop_clock(mmc);
> +     if (ret)
> +             return ret;
> +
> +     /* If we're doing data transfer, configure the controller accordingly */
> +     if (data) {
> +             writel(data->blocks, &regs->nob);
> +             writel(data->blocksize, &regs->blklen);
> +             /* This delay can be optimized, but stick with max value */
> +             writel(0xffff, &regs->rdto);
> +             cmdat |= MMC_CMDAT_DATA_EN;
> +             if (data->flags & MMC_DATA_WRITE)
> +                     cmdat |= MMC_CMDAT_WRITE;
> +     }
> +
> +     /* Run in 4bit mode if the card can do it */
> +     if (mmc->bus_width == 4)
> +             cmdat |= MMC_CMDAT_SD_4DAT;
> +
> +     /* Execute the command */
> +     ret = pxa_mmc_start_cmd(mmc, cmd, cmdat);
> +     if (ret)
> +             return ret;
> +
> +     /* Wait until the command completes */
> +     ret = pxa_mmc_wait(mmc, MMC_STAT_END_CMD_RES);
> +     if (ret)
> +             return ret;
> +
> +     /* Read back the result */
> +     ret = pxa_mmc_cmd_done(mmc, cmd);
> +     if (ret)
> +             return ret;
> +
> +     /* In case there was a data transfer scheduled, do it */
> +     if (data) {
> +             if (data->flags & MMC_DATA_WRITE)
> +                     pxa_mmc_do_write_xfer(mmc, data);
> +             else
> +                     pxa_mmc_do_read_xfer(mmc, data);
> +     }
> +
> +     return 0;
> +}
> +
> +static void pxa_mmc_set_ios(struct mmc *mmc)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +     uint32_t tmp;
> +     uint32_t pxa_mmc_clock;
> +
> +     if (!mmc->clock) {
> +             pxa_mmc_stop_clock(mmc);
> +             return;
> +     }
> +
> +     /* PXA3xx can do 26MHz with special settings. */
> +     if (mmc->clock == 26000000) {
> +             writel(0x7, &regs->clkrt);
> +             return;
> +     }
> +
> +     /* Set clock to the card the usual way. */
> +     pxa_mmc_clock = 0;
> +     tmp = mmc->f_max / mmc->clock;
> +     tmp += tmp % 2;
> +
> +     while (tmp > 1) {
> +             pxa_mmc_clock++;
> +             tmp >>= 1;
> +     }
> +
> +     writel(pxa_mmc_clock, &regs->clkrt);
> +}
> +
> +static int pxa_mmc_init(struct mmc *mmc)
> +{
> +     struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
> +     struct pxa_mmc_regs *regs = priv->regs;
> +
> +     /* Make sure the clock are stopped */
> +     pxa_mmc_stop_clock(mmc);
> +
> +     /* Turn off SPI mode */
> +     writel(0, &regs->spi);
> +
> +     /* Set up maximum timeout to wait for command response */
> +     writel(MMC_RES_TO_MAX_MASK, &regs->resto);
> +
> +     /* Mask all interrupts */
> +     writel(~(MMC_I_MASK_TXFIFO_WR_REQ | MMC_I_MASK_RXFIFO_RD_REQ),
> +             &regs->i_mask);
> +     return 0;
> +}
> +
> +int pxa_mmc_register(int card_index)
> +{
> +     struct mmc *mmc;
> +     struct pxa_mmc_priv *priv;
> +     uint32_t reg;
> +     int ret = -ENOMEM;
> +
> +     mmc = malloc(sizeof(struct mmc));
> +     if (!mmc)
> +             goto err0;
> +
> +     priv = malloc(sizeof(struct pxa_mmc_priv));
> +     if (!priv)
> +             goto err1;
> +
> +     switch (card_index) {
> +     case 0:
> +             priv->regs = (struct pxa_mmc_regs *)MMC0_BASE;
> +             break;
> +     case 1:
> +             priv->regs = (struct pxa_mmc_regs *)MMC1_BASE;
> +             break;
> +     default:
> +             printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n",
> +                     card_index);
> +             goto err2;
> +     }
> +
> +     mmc->priv = priv;
> +
> +     sprintf(mmc->name, "PXA MMC");
> +     mmc->send_cmd   = pxa_mmc_request;
> +     mmc->set_ios    = pxa_mmc_set_ios;
> +     mmc->init       = pxa_mmc_init;
> +
> +     mmc->voltages   = MMC_VDD_32_33 | MMC_VDD_33_34;
> +     mmc->f_max      = PXAMMC_MAX_SPEED;
> +     mmc->f_min      = PXAMMC_MIN_SPEED;
> +     mmc->host_caps  = PXAMMC_HOST_CAPS;
> +
> +     mmc->b_max = 0;
> +
> +#ifndef      CONFIG_CPU_MONAHANS     /* PXA2xx */
> +     reg = readl(CKEN);
> +     reg |= CKEN12_MMC;
> +     writel(reg, CKEN);
> +#else                                /* PXA3xx */
> +     reg = readl(CKENA);
> +     reg |= CKENA_12_MMC0 | CKENA_13_MMC1;
> +     writel(reg, CKENA);
> +#endif
> +
> +     mmc_register(mmc);
> +
> +     return 0;
> +
> +err2:
> +     free(priv);
> +err1:
> +     free(mmc);
> +err0:
> +     return ret;
> +}

-- 
Regards,
Igor.
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to