From 0ff9e4800f21e4250ac8a6ca908de00851f896d8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 13 Jun 2018 08:02:55 +0200 Subject: [PATCH 01/12] pinctrl: renesas: Fix DRV register offset Use fixed 4bit size for generating the DRV register element mask, not the size of the value, which can be smaller. Signed-off-by: Marek Vasut Cc: Masahiro Yamada Cc: Nobuhiro Iwamatsu --- drivers/pinctrl/renesas/pfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c index 90011537a85..b3a4ff9049d 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) From 5dbdd3a600906f56a19c9a82a741705988851a28 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Oct 2018 20:34:51 +0100 Subject: [PATCH 02/12] pinctrl: renesas: Add POCCTRL handling to r8a77990 Add definition of the POCCTRL register and bits therein to R8A77990 E3 pincontrol driver. This allows the pincontrol driver to configure SDHI pin voltage according to power-source DT property. Signed-off-by: Marek Vasut Cc: Nobuhiro Iwamatsu --- drivers/pinctrl/renesas/pfc-r8a77990.c | 34 ++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c index a99fd770f2f..78bf3193d54 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), From e5cb6bd9a2db28338d3595bb3ea30f63624936d6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Oct 2018 15:06:50 +0100 Subject: [PATCH 03/12] ARM: rmobile: Generate fitting mem_map on Gen3 Patch "ARM: rmobile: Mark 4-64GiB as DRAM on Gen3" marked the entire 64bit DRAM space as cachable. On CortexA57, this might result in odd side effects, where the CPU tries to prefetch from those areas and if there is no DRAM backing them, CPU bus hang can happen. This patch fixes it by generating the mem_map structure based on the actual memory layout obtained from the DT, thus not marking areas without any DRAM behind them as cachable. Signed-off-by: Marek Vasut Fixes: c1ec34763811d ("ARM: rmobile: Mark 4-64GiB as DRAM on Gen3") Cc: Nobuhiro Iwamatsu --- arch/arm/mach-rmobile/cpu_info.c | 3 + arch/arm/mach-rmobile/memmap-gen3.c | 89 ++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-rmobile/cpu_info.c b/arch/arm/mach-rmobile/cpu_info.c index e110737471b..c9ebc9f40ed 100644 --- a/arch/arm/mach-rmobile/cpu_info.c +++ b/arch/arm/mach-rmobile/cpu_info.c @@ -6,6 +6,8 @@ #include #include +/* 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 92c8f2e80db..7e29ccc351b 100644 --- a/arch/arm/mach-rmobile/memmap-gen3.c +++ b/arch/arm/mach-rmobile/memmap-gen3.c @@ -8,7 +8,9 @@ #include #include -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(); +} From 645a575aeb384c7bf4ffb1204a93d140c0984fee Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 28 Oct 2018 13:54:10 +0100 Subject: [PATCH 04/12] mmc: tmio: Simplify pinmux handling The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those. Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470a..5f927c6150d 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,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 } From b22c8d0de484f9a4fe677bc2f9de026771605666 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 30 Oct 2018 21:53:29 +0100 Subject: [PATCH 05/12] mmc: tmio: Improve error handling Properly handle return values and abort operations when they are non-zero. This is a minor improvement, which fixes two remaining unchecked return values. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/tmio-common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 5f927c6150d..f1ce019db5a 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -498,6 +498,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, ret = tmio_sd_dma_xfer(dev, data); else ret = tmio_sd_pio_xfer(dev, data); + if (ret) + return ret; ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, TMIO_SD_INFO1_CMP); @@ -505,9 +507,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, return ret; } - tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN); - - return ret; + return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, + TMIO_SD_INFO2_SCLKDIVEN); } static int tmio_sd_set_bus_width(struct tmio_sd_priv *priv, From 33633ebb1c9a25a439dadea9818bfcdac46cdfff Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 30 Oct 2018 22:05:54 +0100 Subject: [PATCH 06/12] mmc: tmio: Silence transfer errors when tuning In case the controller performs card tuning, that is, sends MMC command 19 or 21, silence possible CRC error warning prints. The warnings are bound to happen, since the tuning will fail for some settings while searching for the optimal configuration of the bus and that is perfectly OK. This patch passes around the MMC command structure and adds check into tmio_sd_check_error() to avoid printing CRC error warning when the tuning happens. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/tmio-common.c | 45 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index f1ce019db5a..785b6546719 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,17 @@ 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; } - return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, + return tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN); } From 8171f99e7db072383e20125e54c59f4a40272892 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 13 Jun 2018 08:02:55 +0200 Subject: [PATCH 07/12] mmc: tmio: Configure clock before any other IOS Configure the clock settings before reconfiguring any other IO settings. This is required when the clock must be stopped before changing eg. the pin configuration or any of the other properties of the bus. Running the clock configuration first allows the MMC core to do just that. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/tmio-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 785b6546719..2a73829d994 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -642,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; From c83da2ebc01cffbf5659d1a30960f9fec943c806 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 13 Jun 2018 08:02:55 +0200 Subject: [PATCH 08/12] mmc: tmio: Preinitialize regulator to 3.3V Preinitialize the SD card signals regulator to 3.3V, which is the default post-reset setting, to be sure the regulator is set to a valid value. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/tmio-common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 2a73829d994..0eca83a0f4d 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -720,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); From 52e17968836525fdb1e806d482093bd4cfd7b604 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 28 Oct 2018 15:30:06 +0100 Subject: [PATCH 09/12] mmc: tmio: sdhi: Touch SCC only when UHS capable Add check to avoid touching the SCC tuning registers in case the IP doesn't support them or if the support isn't in place yet. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/renesas-sdhi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce1..7c92bd92ad6 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -294,7 +294,8 @@ 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; @@ -373,7 +374,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; From dc1488f1d26d103449db3436f43fcd81712cb47c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 13 Jun 2018 08:02:55 +0200 Subject: [PATCH 10/12] mmc: tmio: sdhi: Clear HS400 settings when resetting SCC Make sure to clear HS400 configuration when resetting the SCC block. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/renesas-sdhi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 7c92bd92ad6..e92bbe5f096 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 @@ -90,6 +92,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); From 2fc10754d1902ddc2aa3ecd2f0e976a1714a6780 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 28 Oct 2018 19:28:56 +0100 Subject: [PATCH 11/12] mmc: tmio: sdhi: Implement waiting for DAT0 line state When the bus switches to 1.8V mode of operation, it is necessary to verify that the card correctly initiated and completed the voltage switch. This is done by reading out the state of DATA0 line. This patch implement support for reading out the state of the DATA0 line, so the MMC core code can correctly switch to 1.8V mode. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/renesas-sdhi.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index e92bbe5f096..63561e19c82 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -308,13 +308,38 @@ static int renesas_sdhi_set_ios(struct udevice *dev) 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 From a376dde1deb9cc42e3804b9c654f873c936cc8d4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 13 Jun 2018 08:02:55 +0200 Subject: [PATCH 12/12] mmc: tmio: sdhi: Merge DTCNTL access into single register write It is perfectly fine to write th DTCNTL TAP count and enable the SCC sampling clock operation in the same write. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/renesas-sdhi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 63561e19c82..e7f96f8bf22 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -51,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;