
The Renesas RCar Gen3 contains the same controller, originally Matsushita. This patch adds support for handling of the 64bit FIFO on this controller.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com Cc: Jaehoon Chung jh80.chung@samsung.com --- V2: - Use unsigned int for the reg argument of IO accessors - Rework the handling of aligned and unaligned data --- drivers/mmc/uniphier-sd.c | 101 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 18 deletions(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 742d936d98..12b2f1f38f 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -135,6 +135,23 @@ struct uniphier_sd_priv { #define UNIPHIER_SD_CAP_64BIT BIT(3) /* Controller is 64bit */ };
+static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + return readq(priv->regbase + (reg << 1)); + else + return readq(priv->regbase + reg); +} + +static void uniphier_sd_writeq(struct uniphier_sd_priv *priv, + const u64 val, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + writeq(val, priv->regbase + (reg << 1)); + else + writeq(val, priv->regbase + reg); +} + static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg) { if (priv->caps & UNIPHIER_SD_CAP_64BIT) @@ -229,7 +246,7 @@ static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg, return 0; }
-static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf, +static int uniphier_sd_pio_read_one_block(struct udevice *dev, char *pbuf, uint blocksize) { struct uniphier_sd_priv *priv = dev_get_priv(dev); @@ -247,20 +264,42 @@ static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf, */ uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
- if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { - for (i = 0; i < blocksize / 4; i++) - *(*pbuf)++ = uniphier_sd_readl(priv, UNIPHIER_SD_BUF); + if (priv->caps & UNIPHIER_SD_CAP_64BIT) { + u64 *buf = (u64 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 8))) { + for (i = 0; i < blocksize / 8; i++) { + *buf++ = uniphier_sd_readq(priv, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 8; i++) { + u64 data; + data = uniphier_sd_readq(priv, + UNIPHIER_SD_BUF); + put_unaligned(data, buf++); + } + } } else { - for (i = 0; i < blocksize / 4; i++) - put_unaligned(uniphier_sd_readl(priv, UNIPHIER_SD_BUF), - (*pbuf)++); + u32 *buf = (u32 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 4))) { + for (i = 0; i < blocksize / 4; i++) { + *buf++ = uniphier_sd_readl(priv, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 4; i++) { + u32 data; + data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF); + put_unaligned(data, buf++); + } + } }
return 0; }
static int uniphier_sd_pio_write_one_block(struct udevice *dev, - const u32 **pbuf, uint blocksize) + const char *pbuf, uint blocksize) { struct uniphier_sd_priv *priv = dev_get_priv(dev); int i, ret; @@ -273,13 +312,34 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev,
uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
- if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { - for (i = 0; i < blocksize / 4; i++) - uniphier_sd_writel(priv, *(*pbuf)++, UNIPHIER_SD_BUF); + if (priv->caps & UNIPHIER_SD_CAP_64BIT) { + const u64 *buf = (const u64 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 8))) { + for (i = 0; i < blocksize / 8; i++) { + uniphier_sd_writeq(priv, *buf++, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 8; i++) { + u64 data = get_unaligned(buf++); + uniphier_sd_writeq(priv, data, + UNIPHIER_SD_BUF); + } + } } else { - for (i = 0; i < blocksize / 4; i++) - uniphier_sd_writel(priv, get_unaligned((*pbuf)++), - UNIPHIER_SD_BUF); + const u32 *buf = (const u32 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 4))) { + for (i = 0; i < blocksize / 4; i++) { + uniphier_sd_writel(priv, *buf++, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 4; i++) { + u32 data = get_unaligned(buf++); + uniphier_sd_writel(priv, data, + UNIPHIER_SD_BUF); + } + } }
return 0; @@ -287,19 +347,24 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev,
static int uniphier_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) { - u32 *dest = (u32 *)data->dest; - const u32 *src = (const u32 *)data->src; + const char *src = data->src; + char *dest = data->dest; int i, ret;
for (i = 0; i < data->blocks; i++) { if (data->flags & MMC_DATA_READ) - ret = uniphier_sd_pio_read_one_block(dev, &dest, + ret = uniphier_sd_pio_read_one_block(dev, dest, data->blocksize); else - ret = uniphier_sd_pio_write_one_block(dev, &src, + ret = uniphier_sd_pio_write_one_block(dev, src, data->blocksize); if (ret) return ret; + + if (data->flags & MMC_DATA_READ) + dest += data->blocksize; + else + src += data->blocksize; }
return 0;