123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- /*
- * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
- *
- * Loosely based on the old code and Linux's PXA MMC driver
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <common.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/regs-mmc.h>
- #include <linux/errno.h>
- #include <asm/io.h>
- #include <malloc.h>
- #include <mmc.h>
- /* PXAMMC Generic default config for various CPUs */
- #if defined(CONFIG_CPU_PXA25X)
- #define PXAMMC_FIFO_SIZE 1
- #define PXAMMC_MIN_SPEED 312500
- #define PXAMMC_MAX_SPEED 20000000
- #define PXAMMC_HOST_CAPS (0)
- #elif defined(CONFIG_CPU_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)
- #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 = 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(®s->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 = mmc->priv;
- struct pxa_mmc_regs *regs = priv->regs;
- unsigned int timeout = PXA_MMC_TIMEOUT;
- /* If the clock aren't running, exit */
- if (!(readl(®s->stat) & MMC_STAT_CLK_EN))
- return 0;
- /* Tell the controller to turn off the clock */
- writel(MMC_STRPCL_STOP_CLK, ®s->strpcl);
- /* Wait until the clock are off */
- while (--timeout) {
- if (!(readl(®s->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 = mmc->priv;
- struct pxa_mmc_regs *regs = priv->regs;
- int ret;
- /* The card can send a "busy" response */
- if (cmd->resp_type & 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, ®s->cmd);
- writel(cmd->cmdarg >> 16, ®s->argh);
- writel(cmd->cmdarg & 0xffff, ®s->argl);
- writel(cmdat, ®s->cmdat);
- /* Start the controller clock and wait until they are started */
- writel(MMC_STRPCL_START_CLK, ®s->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 = mmc->priv;
- struct pxa_mmc_regs *regs = priv->regs;
- uint32_t a, b, c;
- int i;
- int stat;
- /* Read the controller status */
- stat = readl(®s->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(®s->res) & 0xffff;
- for (i = 0; i < 4; i++) {
- b = readl(®s->res) & 0xffff;
- c = readl(®s->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->resp_type & MMC_RSP_CRC) {
- #ifdef PXAMMC_CRC_SKIP
- if (cmd->resp_type & 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 = 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(®s->i_reg) & MMC_I_REG_RXFIFO_RD_REQ) {
- size = min(len, (uint32_t)PXAMMC_FIFO_SIZE);
- len -= size;
- size /= 4;
- /* Read data into the buffer */
- while (size--)
- *buf++ = readl(®s->rxfifo);
- }
- if (readl(®s->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 = 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(®s->i_reg) & MMC_I_REG_TXFIFO_WR_REQ) {
- size = min(len, (uint32_t)PXAMMC_FIFO_SIZE);
- len -= size;
- size /= 4;
- while (size--)
- writel(*buf++, ®s->txfifo);
- if (min(len, (uint32_t)PXAMMC_FIFO_SIZE) < 32)
- writel(MMC_PRTBUF_BUF_PART_FULL, ®s->prtbuf);
- }
- if (readl(®s->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 = 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, ®s->nob);
- writel(data->blocksize, ®s->blklen);
- /* This delay can be optimized, but stick with max value */
- writel(0xffff, ®s->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 int pxa_mmc_set_ios(struct mmc *mmc)
- {
- struct pxa_mmc_priv *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, ®s->clkrt);
- return;
- }
- /* Set clock to the card the usual way. */
- pxa_mmc_clock = 0;
- tmp = mmc->cfg->f_max / mmc->clock;
- tmp += tmp % 2;
- while (tmp > 1) {
- pxa_mmc_clock++;
- tmp >>= 1;
- }
- writel(pxa_mmc_clock, ®s->clkrt);
- return 0;
- }
- static int pxa_mmc_init(struct mmc *mmc)
- {
- struct pxa_mmc_priv *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, ®s->spi);
- /* Set up maximum timeout to wait for command response */
- writel(MMC_RES_TO_MAX_MASK, ®s->resto);
- /* Mask all interrupts */
- writel(~(MMC_I_MASK_TXFIFO_WR_REQ | MMC_I_MASK_RXFIFO_RD_REQ),
- ®s->i_mask);
- return 0;
- }
- static const struct mmc_ops pxa_mmc_ops = {
- .send_cmd = pxa_mmc_request,
- .set_ios = pxa_mmc_set_ios,
- .init = pxa_mmc_init,
- };
- static struct mmc_config pxa_mmc_cfg = {
- .name = "PXA MMC",
- .ops = &pxa_mmc_ops,
- .voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
- .f_max = PXAMMC_MAX_SPEED,
- .f_min = PXAMMC_MIN_SPEED,
- .host_caps = PXAMMC_HOST_CAPS,
- .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
- };
- int pxa_mmc_register(int card_index)
- {
- struct mmc *mmc;
- struct pxa_mmc_priv *priv;
- uint32_t reg;
- int ret = -ENOMEM;
- priv = malloc(sizeof(struct pxa_mmc_priv));
- if (!priv)
- goto err0;
- memset(priv, 0, sizeof(*priv));
- 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:
- ret = -EINVAL;
- printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n",
- card_index);
- goto err1;
- }
- #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 = mmc_create(&pxa_mmc_cfg, priv);
- if (mmc == NULL)
- goto err1;
- return 0;
- err1:
- free(priv);
- err0:
- return ret;
- }
|