u-boot/drivers/mmc/pxa_mmc_gen.c
Tom Rini 3135ba642f arm: pxa: Remove CONFIG_CPU_PXA25X
There are no platforms that set this, remove the code.

Signed-off-by: Tom Rini <trini@konsulko.com>
2022-06-06 12:09:12 -04:00

531 lines
12 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
*
* Modified to add driver model (DM) support
* Copyright (C) 2019 Marcel Ziswiler <marcel@ziswiler.com>
*
* Loosely based on the old code and Linux's PXA MMC driver
*/
#include <common.h>
#include <asm/arch/hardware.h>
#include <asm/arch/regs-mmc.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <asm/io.h>
#include <dm.h>
#include <dm/platform_data/pxa_mmc_gen.h>
#include <malloc.h>
#include <mmc.h>
/* PXAMMC Generic default config for various CPUs */
#if 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(&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 = 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 = 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, &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 = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
u32 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->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;
u32 len;
u32 *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, (uint32_t)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 = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
u32 len;
u32 *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, (uint32_t)PXAMMC_FIFO_SIZE);
len -= size;
size /= 4;
while (size--)
writel(*buf++, &regs->txfifo);
if (min(len, (uint32_t)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_send_cmd_common(struct pxa_mmc_priv *priv, struct mmc *mmc,
struct mmc_cmd *cmd, struct mmc_data *data)
{
struct pxa_mmc_regs *regs = priv->regs;
u32 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 int pxa_mmc_set_ios_common(struct pxa_mmc_priv *priv, struct mmc *mmc)
{
struct pxa_mmc_regs *regs = priv->regs;
u32 tmp;
u32 pxa_mmc_clock;
if (!mmc->clock) {
pxa_mmc_stop_clock(mmc);
return 0;
}
/* PXA3xx can do 26MHz with special settings. */
if (mmc->clock == 26000000) {
writel(0x7, &regs->clkrt);
return 0;
}
/* 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, &regs->clkrt);
return 0;
}
static int pxa_mmc_init_common(struct pxa_mmc_priv *priv, struct mmc *mmc)
{
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;
}
#if !CONFIG_IS_ENABLED(DM_MMC)
static int pxa_mmc_init(struct mmc *mmc)
{
struct pxa_mmc_priv *priv = mmc->priv;
return pxa_mmc_init_common(priv, mmc);
}
static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct pxa_mmc_priv *priv = mmc->priv;
return pxa_mmc_send_cmd_common(priv, mmc, cmd, data);
}
static int pxa_mmc_set_ios(struct mmc *mmc)
{
struct pxa_mmc_priv *priv = mmc->priv;
return pxa_mmc_set_ios_common(priv, mmc);
}
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;
u32 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)
goto err1;
return 0;
err1:
free(priv);
err0:
return ret;
}
#else /* !CONFIG_IS_ENABLED(DM_MMC) */
static int pxa_mmc_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct pxa_mmc_plat *plat = dev_get_plat(dev);
struct mmc_config *cfg = &plat->cfg;
struct mmc *mmc = &plat->mmc;
struct pxa_mmc_priv *priv = dev_get_priv(dev);
u32 reg;
upriv->mmc = mmc;
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
cfg->f_max = PXAMMC_MAX_SPEED;
cfg->f_min = PXAMMC_MIN_SPEED;
cfg->host_caps = PXAMMC_HOST_CAPS;
cfg->name = dev->name;
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->priv = priv;
priv->regs = plat->base;
#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
return pxa_mmc_init_common(priv, mmc);
}
static int pxa_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct pxa_mmc_plat *plat = dev_get_plat(dev);
struct pxa_mmc_priv *priv = dev_get_priv(dev);
return pxa_mmc_send_cmd_common(priv, &plat->mmc, cmd, data);
}
static int pxa_mmc_set_ios(struct udevice *dev)
{
struct pxa_mmc_plat *plat = dev_get_plat(dev);
struct pxa_mmc_priv *priv = dev_get_priv(dev);
return pxa_mmc_set_ios_common(priv, &plat->mmc);
}
static const struct dm_mmc_ops pxa_mmc_ops = {
.get_cd = NULL,
.send_cmd = pxa_mmc_send_cmd,
.set_ios = pxa_mmc_set_ios,
};
#if CONFIG_IS_ENABLED(BLK)
static int pxa_mmc_bind(struct udevice *dev)
{
struct pxa_mmc_plat *plat = dev_get_plat(dev);
return mmc_bind(dev, &plat->mmc, &plat->cfg);
}
#endif
U_BOOT_DRIVER(pxa_mmc) = {
#if CONFIG_IS_ENABLED(BLK)
.bind = pxa_mmc_bind,
#endif
.id = UCLASS_MMC,
.name = "pxa_mmc",
.ops = &pxa_mmc_ops,
.priv_auto = sizeof(struct pxa_mmc_priv),
.probe = pxa_mmc_probe,
};
#endif /* !CONFIG_IS_ENABLED(DM_MMC) */