183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2e94cad93SMarek Vasut /* 3e94cad93SMarek Vasut * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com> 4e94cad93SMarek Vasut */ 5e94cad93SMarek Vasut 6e94cad93SMarek Vasut #include <common.h> 7e94cad93SMarek Vasut #include <clk.h> 8e94cad93SMarek Vasut #include <fdtdec.h> 9e94cad93SMarek Vasut #include <mmc.h> 10e94cad93SMarek Vasut #include <dm.h> 11e94cad93SMarek Vasut #include <linux/compat.h> 12e94cad93SMarek Vasut #include <linux/dma-direction.h> 13e94cad93SMarek Vasut #include <linux/io.h> 14e94cad93SMarek Vasut #include <linux/sizes.h> 15e94cad93SMarek Vasut #include <power/regulator.h> 16e94cad93SMarek Vasut #include <asm/unaligned.h> 17e94cad93SMarek Vasut 18cb0b6b03SMarek Vasut #include "tmio-common.h" 19e94cad93SMarek Vasut 20f63968baSMarek Vasut #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) 21f63968baSMarek Vasut 22f63968baSMarek Vasut /* SCC registers */ 23f63968baSMarek Vasut #define RENESAS_SDHI_SCC_DTCNTL 0x800 24f63968baSMarek Vasut #define RENESAS_SDHI_SCC_DTCNTL_TAPEN BIT(0) 25f63968baSMarek Vasut #define RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT 16 26f63968baSMarek Vasut #define RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK 0xff 27f63968baSMarek Vasut #define RENESAS_SDHI_SCC_TAPSET 0x804 28f63968baSMarek Vasut #define RENESAS_SDHI_SCC_DT2FF 0x808 29f63968baSMarek Vasut #define RENESAS_SDHI_SCC_CKSEL 0x80c 30f63968baSMarek Vasut #define RENESAS_SDHI_SCC_CKSEL_DTSEL BIT(0) 31f63968baSMarek Vasut #define RENESAS_SDHI_SCC_RVSCNTL 0x810 32f63968baSMarek Vasut #define RENESAS_SDHI_SCC_RVSCNTL_RVSEN BIT(0) 33f63968baSMarek Vasut #define RENESAS_SDHI_SCC_RVSREQ 0x814 34f63968baSMarek Vasut #define RENESAS_SDHI_SCC_RVSREQ_RVSERR BIT(2) 35f63968baSMarek Vasut #define RENESAS_SDHI_SCC_SMPCMP 0x818 36f63968baSMarek Vasut #define RENESAS_SDHI_SCC_TMPPORT2 0x81c 37f63968baSMarek Vasut 38f63968baSMarek Vasut #define RENESAS_SDHI_MAX_TAP 3 39f63968baSMarek Vasut 40cb0b6b03SMarek Vasut static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv) 41f63968baSMarek Vasut { 42f63968baSMarek Vasut u32 reg; 43f63968baSMarek Vasut 44f63968baSMarek Vasut /* Initialize SCC */ 45cb0b6b03SMarek Vasut tmio_sd_writel(priv, 0, TMIO_SD_INFO1); 46f63968baSMarek Vasut 47cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL); 48cb0b6b03SMarek Vasut reg &= ~TMIO_SD_CLKCTL_SCLKEN; 49cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL); 50f63968baSMarek Vasut 51f63968baSMarek Vasut /* Set sampling clock selection range */ 52cb0b6b03SMarek Vasut tmio_sd_writel(priv, 0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT, 53f63968baSMarek Vasut RENESAS_SDHI_SCC_DTCNTL); 54f63968baSMarek Vasut 55cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL); 56f63968baSMarek Vasut reg |= RENESAS_SDHI_SCC_DTCNTL_TAPEN; 57cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_DTCNTL); 58f63968baSMarek Vasut 59cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL); 60f63968baSMarek Vasut reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL; 61cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL); 62f63968baSMarek Vasut 63cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL); 64f63968baSMarek Vasut reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN; 65cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL); 66f63968baSMarek Vasut 67cb0b6b03SMarek Vasut tmio_sd_writel(priv, 0x300 /* scc_tappos */, 68f63968baSMarek Vasut RENESAS_SDHI_SCC_DT2FF); 69f63968baSMarek Vasut 70cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL); 71cb0b6b03SMarek Vasut reg |= TMIO_SD_CLKCTL_SCLKEN; 72cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL); 73f63968baSMarek Vasut 74f63968baSMarek Vasut /* Read TAPNUM */ 75cb0b6b03SMarek Vasut return (tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL) >> 76f63968baSMarek Vasut RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) & 77f63968baSMarek Vasut RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK; 78f63968baSMarek Vasut } 79f63968baSMarek Vasut 80cb0b6b03SMarek Vasut static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv) 81f63968baSMarek Vasut { 82f63968baSMarek Vasut u32 reg; 83f63968baSMarek Vasut 84f63968baSMarek Vasut /* Reset SCC */ 85cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL); 86cb0b6b03SMarek Vasut reg &= ~TMIO_SD_CLKCTL_SCLKEN; 87cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL); 88f63968baSMarek Vasut 89cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL); 90f63968baSMarek Vasut reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL; 91cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL); 92f63968baSMarek Vasut 93cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL); 94cb0b6b03SMarek Vasut reg |= TMIO_SD_CLKCTL_SCLKEN; 95cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL); 96f63968baSMarek Vasut 97cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL); 98f63968baSMarek Vasut reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN; 99cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL); 100f63968baSMarek Vasut 101cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL); 102f63968baSMarek Vasut reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN; 103cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL); 104f63968baSMarek Vasut } 105f63968baSMarek Vasut 106cb0b6b03SMarek Vasut static void renesas_sdhi_prepare_tuning(struct tmio_sd_priv *priv, 107f63968baSMarek Vasut unsigned long tap) 108f63968baSMarek Vasut { 109f63968baSMarek Vasut /* Set sampling clock position */ 110cb0b6b03SMarek Vasut tmio_sd_writel(priv, tap, RENESAS_SDHI_SCC_TAPSET); 111f63968baSMarek Vasut } 112f63968baSMarek Vasut 113cb0b6b03SMarek Vasut static unsigned int renesas_sdhi_compare_scc_data(struct tmio_sd_priv *priv) 114f63968baSMarek Vasut { 115f63968baSMarek Vasut /* Get comparison of sampling data */ 116cb0b6b03SMarek Vasut return tmio_sd_readl(priv, RENESAS_SDHI_SCC_SMPCMP); 117f63968baSMarek Vasut } 118f63968baSMarek Vasut 119cb0b6b03SMarek Vasut static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv, 120f63968baSMarek Vasut unsigned int tap_num, unsigned int taps, 121f63968baSMarek Vasut unsigned int smpcmp) 122f63968baSMarek Vasut { 123f63968baSMarek Vasut unsigned long tap_cnt; /* counter of tuning success */ 124f63968baSMarek Vasut unsigned long tap_set; /* tap position */ 125f63968baSMarek Vasut unsigned long tap_start;/* start position of tuning success */ 126f63968baSMarek Vasut unsigned long tap_end; /* end position of tuning success */ 127f63968baSMarek Vasut unsigned long ntap; /* temporary counter of tuning success */ 128f63968baSMarek Vasut unsigned long match_cnt;/* counter of matching data */ 129f63968baSMarek Vasut unsigned long i; 130f63968baSMarek Vasut bool select = false; 131f63968baSMarek Vasut u32 reg; 132f63968baSMarek Vasut 133f63968baSMarek Vasut /* Clear SCC_RVSREQ */ 134cb0b6b03SMarek Vasut tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ); 135f63968baSMarek Vasut 136f63968baSMarek Vasut /* Merge the results */ 137f63968baSMarek Vasut for (i = 0; i < tap_num * 2; i++) { 138f63968baSMarek Vasut if (!(taps & BIT(i))) { 139f63968baSMarek Vasut taps &= ~BIT(i % tap_num); 140f63968baSMarek Vasut taps &= ~BIT((i % tap_num) + tap_num); 141f63968baSMarek Vasut } 142f63968baSMarek Vasut if (!(smpcmp & BIT(i))) { 143f63968baSMarek Vasut smpcmp &= ~BIT(i % tap_num); 144f63968baSMarek Vasut smpcmp &= ~BIT((i % tap_num) + tap_num); 145f63968baSMarek Vasut } 146f63968baSMarek Vasut } 147f63968baSMarek Vasut 148f63968baSMarek Vasut /* 149f63968baSMarek Vasut * Find the longest consecutive run of successful probes. If that 150f63968baSMarek Vasut * is more than RENESAS_SDHI_MAX_TAP probes long then use the 151f63968baSMarek Vasut * center index as the tap. 152f63968baSMarek Vasut */ 153f63968baSMarek Vasut tap_cnt = 0; 154f63968baSMarek Vasut ntap = 0; 155f63968baSMarek Vasut tap_start = 0; 156f63968baSMarek Vasut tap_end = 0; 157f63968baSMarek Vasut for (i = 0; i < tap_num * 2; i++) { 158f63968baSMarek Vasut if (taps & BIT(i)) 159f63968baSMarek Vasut ntap++; 160f63968baSMarek Vasut else { 161f63968baSMarek Vasut if (ntap > tap_cnt) { 162f63968baSMarek Vasut tap_start = i - ntap; 163f63968baSMarek Vasut tap_end = i - 1; 164f63968baSMarek Vasut tap_cnt = ntap; 165f63968baSMarek Vasut } 166f63968baSMarek Vasut ntap = 0; 167f63968baSMarek Vasut } 168f63968baSMarek Vasut } 169f63968baSMarek Vasut 170f63968baSMarek Vasut if (ntap > tap_cnt) { 171f63968baSMarek Vasut tap_start = i - ntap; 172f63968baSMarek Vasut tap_end = i - 1; 173f63968baSMarek Vasut tap_cnt = ntap; 174f63968baSMarek Vasut } 175f63968baSMarek Vasut 176f63968baSMarek Vasut /* 177f63968baSMarek Vasut * If all of the TAP is OK, the sampling clock position is selected by 178f63968baSMarek Vasut * identifying the change point of data. 179f63968baSMarek Vasut */ 180f63968baSMarek Vasut if (tap_cnt == tap_num * 2) { 181f63968baSMarek Vasut match_cnt = 0; 182f63968baSMarek Vasut ntap = 0; 183f63968baSMarek Vasut tap_start = 0; 184f63968baSMarek Vasut tap_end = 0; 185f63968baSMarek Vasut for (i = 0; i < tap_num * 2; i++) { 186f63968baSMarek Vasut if (smpcmp & BIT(i)) 187f63968baSMarek Vasut ntap++; 188f63968baSMarek Vasut else { 189f63968baSMarek Vasut if (ntap > match_cnt) { 190f63968baSMarek Vasut tap_start = i - ntap; 191f63968baSMarek Vasut tap_end = i - 1; 192f63968baSMarek Vasut match_cnt = ntap; 193f63968baSMarek Vasut } 194f63968baSMarek Vasut ntap = 0; 195f63968baSMarek Vasut } 196f63968baSMarek Vasut } 197f63968baSMarek Vasut if (ntap > match_cnt) { 198f63968baSMarek Vasut tap_start = i - ntap; 199f63968baSMarek Vasut tap_end = i - 1; 200f63968baSMarek Vasut match_cnt = ntap; 201f63968baSMarek Vasut } 202f63968baSMarek Vasut if (match_cnt) 203f63968baSMarek Vasut select = true; 204f63968baSMarek Vasut } else if (tap_cnt >= RENESAS_SDHI_MAX_TAP) 205f63968baSMarek Vasut select = true; 206f63968baSMarek Vasut 207f63968baSMarek Vasut if (select) 208f63968baSMarek Vasut tap_set = ((tap_start + tap_end) / 2) % tap_num; 209f63968baSMarek Vasut else 210f63968baSMarek Vasut return -EIO; 211f63968baSMarek Vasut 212f63968baSMarek Vasut /* Set SCC */ 213cb0b6b03SMarek Vasut tmio_sd_writel(priv, tap_set, RENESAS_SDHI_SCC_TAPSET); 214f63968baSMarek Vasut 215f63968baSMarek Vasut /* Enable auto re-tuning */ 216cb0b6b03SMarek Vasut reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL); 217f63968baSMarek Vasut reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN; 218cb0b6b03SMarek Vasut tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL); 219f63968baSMarek Vasut 220f63968baSMarek Vasut return 0; 221f63968baSMarek Vasut } 222f63968baSMarek Vasut 223f63968baSMarek Vasut int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) 224f63968baSMarek Vasut { 225cb0b6b03SMarek Vasut struct tmio_sd_priv *priv = dev_get_priv(dev); 226f63968baSMarek Vasut struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 227f63968baSMarek Vasut struct mmc *mmc = upriv->mmc; 228f63968baSMarek Vasut unsigned int tap_num; 229f63968baSMarek Vasut unsigned int taps = 0, smpcmp = 0; 230f63968baSMarek Vasut int i, ret = 0; 231f63968baSMarek Vasut u32 caps; 232f63968baSMarek Vasut 233f63968baSMarek Vasut /* Only supported on Renesas RCar */ 234cb0b6b03SMarek Vasut if (!(priv->caps & TMIO_SD_CAP_RCAR_UHS)) 235f63968baSMarek Vasut return -EINVAL; 236f63968baSMarek Vasut 237f63968baSMarek Vasut /* clock tuning is not needed for upto 52MHz */ 238f63968baSMarek Vasut if (!((mmc->selected_mode == MMC_HS_200) || 239f63968baSMarek Vasut (mmc->selected_mode == UHS_SDR104) || 240f63968baSMarek Vasut (mmc->selected_mode == UHS_SDR50))) 241f63968baSMarek Vasut return 0; 242f63968baSMarek Vasut 243f63968baSMarek Vasut tap_num = renesas_sdhi_init_tuning(priv); 244f63968baSMarek Vasut if (!tap_num) 245f63968baSMarek Vasut /* Tuning is not supported */ 246f63968baSMarek Vasut goto out; 247f63968baSMarek Vasut 248f63968baSMarek Vasut if (tap_num * 2 >= sizeof(taps) * 8) { 249f63968baSMarek Vasut dev_err(dev, 250f63968baSMarek Vasut "Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n"); 251f63968baSMarek Vasut goto out; 252f63968baSMarek Vasut } 253f63968baSMarek Vasut 254f63968baSMarek Vasut /* Issue CMD19 twice for each tap */ 255f63968baSMarek Vasut for (i = 0; i < 2 * tap_num; i++) { 256f63968baSMarek Vasut renesas_sdhi_prepare_tuning(priv, i % tap_num); 257f63968baSMarek Vasut 258f63968baSMarek Vasut /* Force PIO for the tuning */ 259f63968baSMarek Vasut caps = priv->caps; 260cb0b6b03SMarek Vasut priv->caps &= ~TMIO_SD_CAP_DMA_INTERNAL; 261f63968baSMarek Vasut 262f63968baSMarek Vasut ret = mmc_send_tuning(mmc, opcode, NULL); 263f63968baSMarek Vasut 264f63968baSMarek Vasut priv->caps = caps; 265f63968baSMarek Vasut 266f63968baSMarek Vasut if (ret == 0) 267f63968baSMarek Vasut taps |= BIT(i); 268f63968baSMarek Vasut 269f63968baSMarek Vasut ret = renesas_sdhi_compare_scc_data(priv); 270f63968baSMarek Vasut if (ret == 0) 271f63968baSMarek Vasut smpcmp |= BIT(i); 272f63968baSMarek Vasut 273f63968baSMarek Vasut mdelay(1); 274f63968baSMarek Vasut } 275f63968baSMarek Vasut 276f63968baSMarek Vasut ret = renesas_sdhi_select_tuning(priv, tap_num, taps, smpcmp); 277f63968baSMarek Vasut 278f63968baSMarek Vasut out: 279f63968baSMarek Vasut if (ret < 0) { 280f63968baSMarek Vasut dev_warn(dev, "Tuning procedure failed\n"); 281f63968baSMarek Vasut renesas_sdhi_reset_tuning(priv); 282f63968baSMarek Vasut } 283f63968baSMarek Vasut 284f63968baSMarek Vasut return ret; 285f63968baSMarek Vasut } 286f63968baSMarek Vasut #endif 287f63968baSMarek Vasut 288f63968baSMarek Vasut static int renesas_sdhi_set_ios(struct udevice *dev) 289f63968baSMarek Vasut { 290cb0b6b03SMarek Vasut int ret = tmio_sd_set_ios(dev); 291cf39f3f3SMarek Vasut 292cf39f3f3SMarek Vasut mdelay(10); 293cf39f3f3SMarek Vasut 294f63968baSMarek Vasut #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) 295cb0b6b03SMarek Vasut struct tmio_sd_priv *priv = dev_get_priv(dev); 296f63968baSMarek Vasut 297f63968baSMarek Vasut renesas_sdhi_reset_tuning(priv); 298f63968baSMarek Vasut #endif 299f63968baSMarek Vasut 300f63968baSMarek Vasut return ret; 301f63968baSMarek Vasut } 302f63968baSMarek Vasut 303e94cad93SMarek Vasut static const struct dm_mmc_ops renesas_sdhi_ops = { 304cb0b6b03SMarek Vasut .send_cmd = tmio_sd_send_cmd, 305f63968baSMarek Vasut .set_ios = renesas_sdhi_set_ios, 306cb0b6b03SMarek Vasut .get_cd = tmio_sd_get_cd, 307f63968baSMarek Vasut #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) 308f63968baSMarek Vasut .execute_tuning = renesas_sdhi_execute_tuning, 309f63968baSMarek Vasut #endif 310e94cad93SMarek Vasut }; 311e94cad93SMarek Vasut 312cb0b6b03SMarek Vasut #define RENESAS_GEN2_QUIRKS TMIO_SD_CAP_RCAR_GEN2 313f98833dbSMarek Vasut #define RENESAS_GEN3_QUIRKS \ 314cb0b6b03SMarek Vasut TMIO_SD_CAP_64BIT | TMIO_SD_CAP_RCAR_GEN3 | TMIO_SD_CAP_RCAR_UHS 315f98833dbSMarek Vasut 316e94cad93SMarek Vasut static const struct udevice_id renesas_sdhi_match[] = { 317f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7790", .data = RENESAS_GEN2_QUIRKS }, 318f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7791", .data = RENESAS_GEN2_QUIRKS }, 319f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7792", .data = RENESAS_GEN2_QUIRKS }, 320f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7793", .data = RENESAS_GEN2_QUIRKS }, 321f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7794", .data = RENESAS_GEN2_QUIRKS }, 322f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7795", .data = RENESAS_GEN3_QUIRKS }, 323f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a7796", .data = RENESAS_GEN3_QUIRKS }, 324f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a77965", .data = RENESAS_GEN3_QUIRKS }, 325f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a77970", .data = RENESAS_GEN3_QUIRKS }, 326d629152aSMarek Vasut { .compatible = "renesas,sdhi-r8a77990", .data = RENESAS_GEN3_QUIRKS }, 327f98833dbSMarek Vasut { .compatible = "renesas,sdhi-r8a77995", .data = RENESAS_GEN3_QUIRKS }, 328e94cad93SMarek Vasut { /* sentinel */ } 329e94cad93SMarek Vasut }; 330e94cad93SMarek Vasut 331c769e609SMarek Vasut static int renesas_sdhi_probe(struct udevice *dev) 332c769e609SMarek Vasut { 33330b5d9aaSMasahiro Yamada struct tmio_sd_priv *priv = dev_get_priv(dev); 334c769e609SMarek Vasut u32 quirks = dev_get_driver_data(dev); 3357cf7ef81SMarek Vasut struct fdt_resource reg_res; 33630b5d9aaSMasahiro Yamada struct clk clk; 3377cf7ef81SMarek Vasut DECLARE_GLOBAL_DATA_PTR; 3387cf7ef81SMarek Vasut int ret; 3397cf7ef81SMarek Vasut 340f98833dbSMarek Vasut if (quirks == RENESAS_GEN2_QUIRKS) { 341f98833dbSMarek Vasut ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), 342f98833dbSMarek Vasut "reg", 0, ®_res); 3437cf7ef81SMarek Vasut if (ret < 0) { 344f98833dbSMarek Vasut dev_err(dev, "\"reg\" resource not found, ret=%i\n", 345f98833dbSMarek Vasut ret); 3467cf7ef81SMarek Vasut return ret; 3477cf7ef81SMarek Vasut } 3487cf7ef81SMarek Vasut 349f98833dbSMarek Vasut if (fdt_resource_size(®_res) == 0x100) 350cb0b6b03SMarek Vasut quirks |= TMIO_SD_CAP_16BIT; 351f98833dbSMarek Vasut } 352c769e609SMarek Vasut 35330b5d9aaSMasahiro Yamada ret = clk_get_by_index(dev, 0, &clk); 35430b5d9aaSMasahiro Yamada if (ret < 0) { 35530b5d9aaSMasahiro Yamada dev_err(dev, "failed to get host clock\n"); 35630b5d9aaSMasahiro Yamada return ret; 35730b5d9aaSMasahiro Yamada } 35830b5d9aaSMasahiro Yamada 35930b5d9aaSMasahiro Yamada /* set to max rate */ 36030b5d9aaSMasahiro Yamada priv->mclk = clk_set_rate(&clk, ULONG_MAX); 36130b5d9aaSMasahiro Yamada if (IS_ERR_VALUE(priv->mclk)) { 36230b5d9aaSMasahiro Yamada dev_err(dev, "failed to set rate for host clock\n"); 36330b5d9aaSMasahiro Yamada clk_free(&clk); 36430b5d9aaSMasahiro Yamada return priv->mclk; 36530b5d9aaSMasahiro Yamada } 36630b5d9aaSMasahiro Yamada 36730b5d9aaSMasahiro Yamada ret = clk_enable(&clk); 36830b5d9aaSMasahiro Yamada clk_free(&clk); 36930b5d9aaSMasahiro Yamada if (ret) { 37030b5d9aaSMasahiro Yamada dev_err(dev, "failed to enable host clock\n"); 37130b5d9aaSMasahiro Yamada return ret; 37230b5d9aaSMasahiro Yamada } 37330b5d9aaSMasahiro Yamada 374cb0b6b03SMarek Vasut ret = tmio_sd_probe(dev, quirks); 375f63968baSMarek Vasut #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) 376f63968baSMarek Vasut if (!ret) 377*65186977SMarek Vasut renesas_sdhi_reset_tuning(priv); 378f63968baSMarek Vasut #endif 379f63968baSMarek Vasut return ret; 380c769e609SMarek Vasut } 381c769e609SMarek Vasut 382e94cad93SMarek Vasut U_BOOT_DRIVER(renesas_sdhi) = { 383e94cad93SMarek Vasut .name = "renesas-sdhi", 384e94cad93SMarek Vasut .id = UCLASS_MMC, 385e94cad93SMarek Vasut .of_match = renesas_sdhi_match, 386cb0b6b03SMarek Vasut .bind = tmio_sd_bind, 387c769e609SMarek Vasut .probe = renesas_sdhi_probe, 388cb0b6b03SMarek Vasut .priv_auto_alloc_size = sizeof(struct tmio_sd_priv), 389cb0b6b03SMarek Vasut .platdata_auto_alloc_size = sizeof(struct tmio_sd_plat), 390e94cad93SMarek Vasut .ops = &renesas_sdhi_ops, 391e94cad93SMarek Vasut }; 392