summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-rmobile/cpu_info.c3
-rw-r--r--arch/arm/mach-rmobile/memmap-gen3.c89
-rw-r--r--drivers/mmc/renesas-sdhi.c48
-rw-r--r--drivers/mmc/tmio-common.c76
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a77990.c34
-rw-r--r--drivers/pinctrl/renesas/pfc.c2
6 files changed, 196 insertions, 56 deletions
diff --git a/arch/arm/mach-rmobile/cpu_info.c b/arch/arm/mach-rmobile/cpu_info.c
index e110737471..c9ebc9f40e 100644
--- a/arch/arm/mach-rmobile/cpu_info.c
+++ b/arch/arm/mach-rmobile/cpu_info.c
@@ -6,6 +6,8 @@
#include <common.h>
#include <asm/io.h>
+/* R-Car Gen3 caches are enabled in memmap-gen3.c */
+#ifndef CONFIG_RCAR_GEN3
#ifdef CONFIG_ARCH_CPU_INIT
int arch_cpu_init(void)
{
@@ -20,6 +22,7 @@ void enable_caches(void)
dcache_enable();
}
#endif
+#endif
#ifdef CONFIG_DISPLAY_CPUINFO
static u32 __rmobile_get_cpu_type(void)
diff --git a/arch/arm/mach-rmobile/memmap-gen3.c b/arch/arm/mach-rmobile/memmap-gen3.c
index 92c8f2e80d..7e29ccc351 100644
--- a/arch/arm/mach-rmobile/memmap-gen3.c
+++ b/arch/arm/mach-rmobile/memmap-gen3.c
@@ -8,7 +8,9 @@
#include <common.h>
#include <asm/armv8/mmu.h>
-static struct mm_region gen3_mem_map[] = {
+#define GEN3_NR_REGIONS 16
+
+static struct mm_region gen3_mem_map[GEN3_NR_REGIONS] = {
{
.virt = 0x0UL,
.phys = 0x0UL,
@@ -42,3 +44,88 @@ static struct mm_region gen3_mem_map[] = {
};
struct mm_region *mem_map = gen3_mem_map;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void enable_caches(void)
+{
+ u64 start, size;
+ int bank, i = 0;
+
+ /* Create map for RPC access */
+ gen3_mem_map[i].virt = 0x0ULL;
+ gen3_mem_map[i].phys = 0x0ULL;
+ gen3_mem_map[i].size = 0x40000000ULL;
+ gen3_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN;
+ i++;
+
+ /* Generate entires for DRAM in 32bit address space */
+ for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+ start = gd->bd->bi_dram[bank].start;
+ size = gd->bd->bi_dram[bank].size;
+
+ /* Skip empty DRAM banks */
+ if (!size)
+ continue;
+
+ /* Skip DRAM above 4 GiB */
+ if (start >> 32ULL)
+ continue;
+
+ /* Mark memory reserved by ATF as cacheable too. */
+ if (start == 0x48000000) {
+ start = 0x40000000ULL;
+ size += 0x08000000ULL;
+ }
+
+ gen3_mem_map[i].virt = start;
+ gen3_mem_map[i].phys = start;
+ gen3_mem_map[i].size = size;
+ gen3_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ i++;
+ }
+
+ /* Create map for register access */
+ gen3_mem_map[i].virt = 0xc0000000ULL;
+ gen3_mem_map[i].phys = 0xc0000000ULL;
+ gen3_mem_map[i].size = 0x40000000ULL;
+ gen3_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN;
+ i++;
+
+ /* Generate entires for DRAM in 64bit address space */
+ for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+ start = gd->bd->bi_dram[bank].start;
+ size = gd->bd->bi_dram[bank].size;
+
+ /* Skip empty DRAM banks */
+ if (!size)
+ continue;
+
+ /* Skip DRAM below 4 GiB */
+ if (!(start >> 32ULL))
+ continue;
+
+ gen3_mem_map[i].virt = start;
+ gen3_mem_map[i].phys = start;
+ gen3_mem_map[i].size = size;
+ gen3_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ i++;
+ }
+
+ /* Zero out the remaining regions. */
+ for (; i < GEN3_NR_REGIONS; i++) {
+ gen3_mem_map[i].virt = 0;
+ gen3_mem_map[i].phys = 0;
+ gen3_mem_map[i].size = 0;
+ gen3_mem_map[i].attrs = 0;
+ }
+
+ icache_enable();
+ dcache_enable();
+}
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index f8dc5f57ce..e7f96f8bf2 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -34,6 +34,8 @@
#define RENESAS_SDHI_SCC_RVSREQ_RVSERR BIT(2)
#define RENESAS_SDHI_SCC_SMPCMP 0x818
#define RENESAS_SDHI_SCC_TMPPORT2 0x81c
+#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN BIT(31)
+#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL BIT(4)
#define RENESAS_SDHI_MAX_TAP 3
@@ -49,12 +51,9 @@ static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv)
tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
/* Set sampling clock selection range */
- tmio_sd_writel(priv, 0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT,
- RENESAS_SDHI_SCC_DTCNTL);
-
- reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL);
- reg |= RENESAS_SDHI_SCC_DTCNTL_TAPEN;
- tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_DTCNTL);
+ tmio_sd_writel(priv, (0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
+ RENESAS_SDHI_SCC_DTCNTL_TAPEN,
+ RENESAS_SDHI_SCC_DTCNTL);
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
@@ -90,6 +89,11 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL;
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
+ reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2);
+ reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
+ RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
+ tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
+
reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
reg |= TMIO_SD_CLKCTL_SCLKEN;
tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
@@ -294,19 +298,45 @@ static int renesas_sdhi_set_ios(struct udevice *dev)
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
struct tmio_sd_priv *priv = dev_get_priv(dev);
- renesas_sdhi_reset_tuning(priv);
+ if (priv->caps & TMIO_SD_CAP_RCAR_UHS)
+ renesas_sdhi_reset_tuning(priv);
#endif
return ret;
}
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout)
+{
+ int ret = -ETIMEDOUT;
+ bool dat0_high;
+ bool target_dat0_high = !!state;
+ struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+ timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */
+ while (timeout--) {
+ dat0_high = !!(tmio_sd_readl(priv, TMIO_SD_INFO2) & TMIO_SD_INFO2_DAT0);
+ if (dat0_high == target_dat0_high) {
+ ret = 0;
+ break;
+ }
+ udelay(10);
+ }
+
+ return ret;
+}
+#endif
+
static const struct dm_mmc_ops renesas_sdhi_ops = {
.send_cmd = tmio_sd_send_cmd,
.set_ios = renesas_sdhi_set_ios,
.get_cd = tmio_sd_get_cd,
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
.execute_tuning = renesas_sdhi_execute_tuning,
#endif
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+ .wait_dat0 = renesas_sdhi_wait_dat0,
+#endif
};
#define RENESAS_GEN2_QUIRKS TMIO_SD_CAP_RCAR_GEN2
@@ -373,7 +403,7 @@ static int renesas_sdhi_probe(struct udevice *dev)
ret = tmio_sd_probe(dev, quirks);
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
- if (!ret)
+ if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS))
renesas_sdhi_reset_tuning(priv);
#endif
return ret;
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 138de59470..0eca83a0f4 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -95,7 +95,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size,
invalidate_dcache_range(addr, addr + size);
}
-static int tmio_sd_check_error(struct udevice *dev)
+static int tmio_sd_check_error(struct udevice *dev, struct mmc_cmd *cmd)
{
struct tmio_sd_priv *priv = dev_get_priv(dev);
u32 info2 = tmio_sd_readl(priv, TMIO_SD_INFO2);
@@ -116,7 +116,9 @@ static int tmio_sd_check_error(struct udevice *dev)
if (info2 & (TMIO_SD_INFO2_ERR_END | TMIO_SD_INFO2_ERR_CRC |
TMIO_SD_INFO2_ERR_IDX)) {
- dev_err(dev, "communication out of sync\n");
+ if ((cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK) &&
+ (cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200))
+ dev_err(dev, "communication out of sync\n");
return -EILSEQ;
}
@@ -129,8 +131,8 @@ static int tmio_sd_check_error(struct udevice *dev)
return 0;
}
-static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
- u32 flag)
+static int tmio_sd_wait_for_irq(struct udevice *dev, struct mmc_cmd *cmd,
+ unsigned int reg, u32 flag)
{
struct tmio_sd_priv *priv = dev_get_priv(dev);
long wait = 1000000;
@@ -142,7 +144,7 @@ static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
return -ETIMEDOUT;
}
- ret = tmio_sd_check_error(dev);
+ ret = tmio_sd_check_error(dev, cmd);
if (ret)
return ret;
@@ -178,15 +180,15 @@ tmio_pio_read_fifo(64, q)
tmio_pio_read_fifo(32, l)
tmio_pio_read_fifo(16, w)
-static int tmio_sd_pio_read_one_block(struct udevice *dev, char *pbuf,
- uint blocksize)
+static int tmio_sd_pio_read_one_block(struct udevice *dev, struct mmc_cmd *cmd,
+ char *pbuf, uint blocksize)
{
struct tmio_sd_priv *priv = dev_get_priv(dev);
int ret;
/* wait until the buffer is filled with data */
- ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
- TMIO_SD_INFO2_BRE);
+ ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
+ TMIO_SD_INFO2_BRE);
if (ret)
return ret;
@@ -231,15 +233,15 @@ tmio_pio_write_fifo(64, q)
tmio_pio_write_fifo(32, l)
tmio_pio_write_fifo(16, w)
-static int tmio_sd_pio_write_one_block(struct udevice *dev,
+static int tmio_sd_pio_write_one_block(struct udevice *dev, struct mmc_cmd *cmd,
const char *pbuf, uint blocksize)
{
struct tmio_sd_priv *priv = dev_get_priv(dev);
int ret;
/* wait until the buffer becomes empty */
- ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
- TMIO_SD_INFO2_BWE);
+ ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
+ TMIO_SD_INFO2_BWE);
if (ret)
return ret;
@@ -255,7 +257,8 @@ static int tmio_sd_pio_write_one_block(struct udevice *dev,
return 0;
}
-static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
+static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
{
const char *src = data->src;
char *dest = data->dest;
@@ -263,10 +266,10 @@ static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
for (i = 0; i < data->blocks; i++) {
if (data->flags & MMC_DATA_READ)
- ret = tmio_sd_pio_read_one_block(dev, dest,
+ ret = tmio_sd_pio_read_one_block(dev, cmd, dest,
data->blocksize);
else
- ret = tmio_sd_pio_write_one_block(dev, src,
+ ret = tmio_sd_pio_write_one_block(dev, cmd, src,
data->blocksize);
if (ret)
return ret;
@@ -468,8 +471,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
cmd->cmdidx, tmp, cmd->cmdarg);
tmio_sd_writel(priv, tmp, TMIO_SD_CMD);
- ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
- TMIO_SD_INFO1_RSP);
+ ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1,
+ TMIO_SD_INFO1_RSP);
if (ret)
return ret;
@@ -497,17 +500,18 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
tmio_sd_addr_is_dmaable(data->src))
ret = tmio_sd_dma_xfer(dev, data);
else
- ret = tmio_sd_pio_xfer(dev, data);
+ ret = tmio_sd_pio_xfer(dev, cmd, data);
+ if (ret)
+ return ret;
- ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
- TMIO_SD_INFO1_CMP);
+ ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1,
+ TMIO_SD_INFO1_CMP);
if (ret)
return ret;
}
- tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN);
-
- return ret;
+ return tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
+ TMIO_SD_INFO2_SCLKDIVEN);
}
static int tmio_sd_set_bus_width(struct tmio_sd_priv *priv,
@@ -622,26 +626,10 @@ static void tmio_sd_set_pins(struct udevice *dev)
#endif
#ifdef CONFIG_PINCTRL
- switch (mmc->selected_mode) {
- case MMC_LEGACY:
- case SD_LEGACY:
- case MMC_HS:
- case SD_HS:
- case MMC_HS_52:
- case MMC_DDR_52:
- pinctrl_select_state(dev, "default");
- break;
- case UHS_SDR12:
- case UHS_SDR25:
- case UHS_SDR50:
- case UHS_DDR50:
- case UHS_SDR104:
- case MMC_HS_200:
+ if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
pinctrl_select_state(dev, "state_uhs");
- break;
- default:
- break;
- }
+ else
+ pinctrl_select_state(dev, "default");
#endif
}
@@ -654,11 +642,11 @@ int tmio_sd_set_ios(struct udevice *dev)
dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n",
mmc->clock, mmc->ddr_mode, mmc->bus_width);
+ tmio_sd_set_clk_rate(priv, mmc);
ret = tmio_sd_set_bus_width(priv, mmc);
if (ret)
return ret;
tmio_sd_set_ddr_mode(priv, mmc);
- tmio_sd_set_clk_rate(priv, mmc);
tmio_sd_set_pins(dev);
return 0;
@@ -732,6 +720,8 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
#ifdef CONFIG_DM_REGULATOR
device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev);
+ if (priv->vqmmc_dev)
+ regulator_set_value(priv->vqmmc_dev, 3300000);
#endif
ret = mmc_of_parse(dev, &plat->cfg);
diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c
index a99fd770f2..78bf3193d5 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77990.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77990.c
@@ -26,12 +26,12 @@
PORT_GP_18(0, fn, sfx), \
PORT_GP_23(1, fn, sfx), \
PORT_GP_26(2, fn, sfx), \
- PORT_GP_12(3, fn, sfx), \
+ PORT_GP_CFG_12(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
PORT_GP_1(3, 12, fn, sfx), \
PORT_GP_1(3, 13, fn, sfx), \
PORT_GP_1(3, 14, fn, sfx), \
PORT_GP_1(3, 15, fn, sfx), \
- PORT_GP_11(4, fn, sfx), \
+ PORT_GP_CFG_11(4, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
PORT_GP_20(5, fn, sfx), \
PORT_GP_18(6, fn, sfx)
/*
@@ -5151,8 +5151,37 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
{ },
};
+enum ioctrl_regs {
+ POCCTRL,
+};
+
+static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = {
+ [POCCTRL] = { 0xe6060380, },
+ { /* sentinel */ },
+};
+
+static int r8a77990_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl)
+{
+ int bit = -EINVAL;
+
+ *pocctrl = pinmux_ioctrl_regs[POCCTRL].reg;
+
+ if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 11))
+ bit = pin & 0x1f;
+
+ if (pin >= RCAR_GP_PIN(4, 0) && pin <= RCAR_GP_PIN(4, 10))
+ bit = (pin & 0x1f) + 19;
+
+ return bit;
+}
+
+static const struct sh_pfc_soc_operations r8a77990_pinmux_ops = {
+ .pin_to_pocctrl = r8a77990_pin_to_pocctrl,
+};
+
const struct sh_pfc_soc_info r8a77990_pinmux_info = {
.name = "r8a77990_pfc",
+ .ops = &r8a77990_pinmux_ops,
.unlock_reg = 0xe6060000, /* PMMR */
.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
@@ -5165,6 +5194,7 @@ const struct sh_pfc_soc_info r8a77990_pinmux_info = {
.nr_functions = ARRAY_SIZE(pinmux_functions),
.cfg_regs = pinmux_config_regs,
+ .ioctrl_regs = pinmux_ioctrl_regs,
.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c
index 90011537a8..b3a4ff9049 100644
--- a/drivers/pinctrl/renesas/pfc.c
+++ b/drivers/pinctrl/renesas/pfc.c
@@ -591,7 +591,7 @@ static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc,
strength = strength / step - 1;
val = sh_pfc_read_raw_reg(reg, 32);
- val &= ~GENMASK(offset + size - 1, offset);
+ val &= ~GENMASK(offset + 4 - 1, offset);
val |= strength << offset;
if (unlock_reg)