Lines Matching +full:imx7ulp +full:- +full:usdhc

2  * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc
7 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
9 * SPDX-License-Identifier: GPL-2.0+
25 #include <asm-generic/gpio.h>
55 uint mixctrl; /* For USDHC */
99 * @non_removable: 0: removable; 1: non-removable
132 if (data->blocks > 1) { in esdhc_xfertyp()
140 if (data->flags & MMC_DATA_READ) in esdhc_xfertyp()
144 if (cmd->resp_type & MMC_RSP_CRC) in esdhc_xfertyp()
146 if (cmd->resp_type & MMC_RSP_OPCODE) in esdhc_xfertyp()
148 if (cmd->resp_type & MMC_RSP_136) in esdhc_xfertyp()
150 else if (cmd->resp_type & MMC_RSP_BUSY) in esdhc_xfertyp()
152 else if (cmd->resp_type & MMC_RSP_PRESENT) in esdhc_xfertyp()
155 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) in esdhc_xfertyp()
158 return XFERTYP_CMD(cmd->cmdidx) | xfertyp; in esdhc_xfertyp()
168 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_pio_read_write()
176 if (data->flags & MMC_DATA_READ) { in esdhc_pio_read_write()
177 blocks = data->blocks; in esdhc_pio_read_write()
178 buffer = data->dest; in esdhc_pio_read_write()
181 size = data->blocksize; in esdhc_pio_read_write()
182 irqstat = esdhc_read32(&regs->irqstat); in esdhc_pio_read_write()
183 while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BREN) in esdhc_pio_read_write()
184 && --timeout); in esdhc_pio_read_write()
191 irqstat = esdhc_read32(&regs->irqstat); in esdhc_pio_read_write()
192 databuf = in_le32(&regs->datport); in esdhc_pio_read_write()
195 size -= 4; in esdhc_pio_read_write()
197 blocks--; in esdhc_pio_read_write()
200 blocks = data->blocks; in esdhc_pio_read_write()
201 buffer = (char *)data->src; in esdhc_pio_read_write()
204 size = data->blocksize; in esdhc_pio_read_write()
205 irqstat = esdhc_read32(&regs->irqstat); in esdhc_pio_read_write()
206 while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BWEN) in esdhc_pio_read_write()
207 && --timeout); in esdhc_pio_read_write()
216 size -= 4; in esdhc_pio_read_write()
217 irqstat = esdhc_read32(&regs->irqstat); in esdhc_pio_read_write()
218 out_le32(&regs->datport, databuf); in esdhc_pio_read_write()
220 blocks--; in esdhc_pio_read_write()
230 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_setup_data()
236 wml_value = data->blocksize/4; in esdhc_setup_data()
238 if (data->flags & MMC_DATA_READ) { in esdhc_setup_data()
242 esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value); in esdhc_setup_data()
245 addr = virt_to_phys((void *)(data->dest)); in esdhc_setup_data()
249 esdhc_write32(&regs->dsaddr, lower_32_bits(addr)); in esdhc_setup_data()
251 esdhc_write32(&regs->dsaddr, (u32)data->dest); in esdhc_setup_data()
256 flush_dcache_range((ulong)data->src, in esdhc_setup_data()
257 (ulong)data->src+data->blocks in esdhc_setup_data()
258 *data->blocksize); in esdhc_setup_data()
262 if (priv->wp_enable) { in esdhc_setup_data()
263 if ((esdhc_read32(&regs->prsstat) & in esdhc_setup_data()
266 return -ETIMEDOUT; in esdhc_setup_data()
270 esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK, in esdhc_setup_data()
274 addr = virt_to_phys((void *)(data->src)); in esdhc_setup_data()
278 esdhc_write32(&regs->dsaddr, lower_32_bits(addr)); in esdhc_setup_data()
280 esdhc_write32(&regs->dsaddr, (u32)data->src); in esdhc_setup_data()
285 esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize); in esdhc_setup_data()
293 * = (mmc->clock * 1/4) SD Clock cycles in esdhc_setup_data()
295 * => (2^(timeout+13)) >= mmc->clock * 1/4 in esdhc_setup_data()
297 * => timeout + 13 >= log2(mmc->clock/4) in esdhc_setup_data()
299 * => timeout + 13 = log2(mmc->clock/4) + 1 in esdhc_setup_data()
300 * => timeout + 13 = fls(mmc->clock/4) in esdhc_setup_data()
307 * => timeout + 13 = fls(mmc->clock/2) in esdhc_setup_data()
309 timeout = fls(mmc->clock/2); in esdhc_setup_data()
310 timeout -= 13; in esdhc_setup_data()
326 esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); in esdhc_setup_data()
337 data->blocks*data->blocksize); in check_and_invalidate_dcache_range()
341 addr = virt_to_phys((void *)(data->dest)); in check_and_invalidate_dcache_range()
347 start = (unsigned)data->dest; in check_and_invalidate_dcache_range()
363 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_send_cmd_common()
366 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) in esdhc_send_cmd_common()
370 esdhc_write32(&regs->irqstat, -1); in esdhc_send_cmd_common()
375 while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) || in esdhc_send_cmd_common()
376 (esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB)) in esdhc_send_cmd_common()
379 while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA) in esdhc_send_cmd_common()
395 if (data->flags & MMC_DATA_READ) in esdhc_send_cmd_common()
403 esdhc_write32(&regs->irqsigen, 0); in esdhc_send_cmd_common()
406 esdhc_write32(&regs->cmdarg, cmd->cmdarg); in esdhc_send_cmd_common()
408 esdhc_write32(&regs->mixctrl, in esdhc_send_cmd_common()
409 (esdhc_read32(&regs->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F) in esdhc_send_cmd_common()
411 esdhc_write32(&regs->xfertyp, xfertyp & 0xFFFF0000); in esdhc_send_cmd_common()
413 esdhc_write32(&regs->xfertyp, xfertyp); in esdhc_send_cmd_common()
417 while (!(esdhc_read32(&regs->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE))) in esdhc_send_cmd_common()
420 irqstat = esdhc_read32(&regs->irqstat); in esdhc_send_cmd_common()
423 err = -ECOMM; in esdhc_send_cmd_common()
428 err = -ETIMEDOUT; in esdhc_send_cmd_common()
433 if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) { in esdhc_send_cmd_common()
434 esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT); in esdhc_send_cmd_common()
437 /* Sleep for 5 ms - max time for card to switch to 1.8V */ in esdhc_send_cmd_common()
442 if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { in esdhc_send_cmd_common()
446 while (timeout > 0 && !(esdhc_read32(&regs->prsstat) & in esdhc_send_cmd_common()
449 timeout--; in esdhc_send_cmd_common()
454 err = -ETIMEDOUT; in esdhc_send_cmd_common()
460 if (cmd->resp_type & MMC_RSP_136) { in esdhc_send_cmd_common()
463 cmdrsp3 = esdhc_read32(&regs->cmdrsp3); in esdhc_send_cmd_common()
464 cmdrsp2 = esdhc_read32(&regs->cmdrsp2); in esdhc_send_cmd_common()
465 cmdrsp1 = esdhc_read32(&regs->cmdrsp1); in esdhc_send_cmd_common()
466 cmdrsp0 = esdhc_read32(&regs->cmdrsp0); in esdhc_send_cmd_common()
467 cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); in esdhc_send_cmd_common()
468 cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); in esdhc_send_cmd_common()
469 cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); in esdhc_send_cmd_common()
470 cmd->response[3] = (cmdrsp0 << 8); in esdhc_send_cmd_common()
472 cmd->response[0] = esdhc_read32(&regs->cmdrsp0); in esdhc_send_cmd_common()
480 irqstat = esdhc_read32(&regs->irqstat); in esdhc_send_cmd_common()
483 err = -ETIMEDOUT; in esdhc_send_cmd_common()
488 err = -ECOMM; in esdhc_send_cmd_common()
495 * cache-fill during the DMA operations such as the in esdhc_send_cmd_common()
496 * speculative pre-fetching etc. in esdhc_send_cmd_common()
498 if (data->flags & MMC_DATA_READ) in esdhc_send_cmd_common()
506 esdhc_write32(&regs->sysctl, esdhc_read32(&regs->sysctl) | in esdhc_send_cmd_common()
508 while (esdhc_read32(&regs->sysctl) & SYSCTL_RSTC) in esdhc_send_cmd_common()
512 esdhc_write32(&regs->sysctl, in esdhc_send_cmd_common()
513 esdhc_read32(&regs->sysctl) | in esdhc_send_cmd_common()
515 while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTD)) in esdhc_send_cmd_common()
520 if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) in esdhc_send_cmd_common()
524 esdhc_write32(&regs->irqstat, -1); in esdhc_send_cmd_common()
537 int ddr_pre_div = mmc->ddr_mode ? 2 : 1; in set_sysctl()
538 struct fsl_esdhc *regs = priv->esdhc_regs; in set_sysctl()
539 int sdhc_clk = priv->sdhc_clk; in set_sysctl()
542 if (clock < mmc->cfg->f_min) in set_sysctl()
543 clock = mmc->cfg->f_min; in set_sysctl()
552 div -= 1; in set_sysctl()
557 esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN); in set_sysctl()
559 esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN); in set_sysctl()
562 esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk); in set_sysctl()
567 esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN); in set_sysctl()
569 esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); in set_sysctl()
577 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_clock_control()
581 value = esdhc_read32(&regs->sysctl); in esdhc_clock_control()
588 esdhc_write32(&regs->sysctl, value); in esdhc_clock_control()
592 while (!(esdhc_read32(&regs->prsstat) & value)) { in esdhc_clock_control()
597 time_out--; in esdhc_clock_control()
605 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_set_ios_common()
610 esdhc_setbits32(&regs->scr, ESDHCCTL_PCS); in esdhc_set_ios_common()
614 set_sysctl(priv, mmc, mmc->clock); in esdhc_set_ios_common()
617 esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); in esdhc_set_ios_common()
619 if (mmc->bus_width == 4) in esdhc_set_ios_common()
620 esdhc_setbits32(&regs->proctl, PROCTL_DTW_4); in esdhc_set_ios_common()
621 else if (mmc->bus_width == 8) in esdhc_set_ios_common()
622 esdhc_setbits32(&regs->proctl, PROCTL_DTW_8); in esdhc_set_ios_common()
629 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_init_common()
633 esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA); in esdhc_init_common()
637 while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) { in esdhc_init_common()
639 return -ETIMEDOUT; in esdhc_init_common()
644 esdhc_write32(&regs->mmcboot, 0x0); in esdhc_init_common()
646 esdhc_write32(&regs->mixctrl, 0x0); in esdhc_init_common()
647 esdhc_write32(&regs->clktunectrlstatus, 0x0); in esdhc_init_common()
650 esdhc_write32(&regs->vendorspec, VENDORSPEC_INIT); in esdhc_init_common()
653 esdhc_write32(&regs->dllctrl, 0x0); in esdhc_init_common()
658 esdhc_write32(&regs->scr, 0x00000040); in esdhc_init_common()
662 esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); in esdhc_init_common()
664 esdhc_setbits32(&regs->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN); in esdhc_init_common()
671 esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); in esdhc_init_common()
674 esdhc_write32(&regs->proctl, PROCTL_INIT); in esdhc_init_common()
677 esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); in esdhc_init_common()
679 if (priv->vs18_enable) in esdhc_init_common()
680 esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT); in esdhc_init_common()
687 struct fsl_esdhc *regs = priv->esdhc_regs; in esdhc_getcd_common()
696 if (priv->non_removable) in esdhc_getcd_common()
699 if (dm_gpio_is_valid(&priv->cd_gpio)) in esdhc_getcd_common()
700 return dm_gpio_get_value(&priv->cd_gpio); in esdhc_getcd_common()
704 while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout) in esdhc_getcd_common()
715 esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA); in esdhc_reset()
719 while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) { in esdhc_reset()
722 return -ETIMEDOUT; in esdhc_reset()
732 struct fsl_esdhc_priv *priv = mmc->priv; in esdhc_getcd()
739 struct fsl_esdhc_priv *priv = mmc->priv; in esdhc_init()
747 struct fsl_esdhc_priv *priv = mmc->priv; in esdhc_send_cmd()
754 struct fsl_esdhc_priv *priv = mmc->priv; in esdhc_set_ios()
776 return -EINVAL; in fsl_esdhc_init()
778 regs = priv->esdhc_regs; in fsl_esdhc_init()
786 esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN in fsl_esdhc_init()
789 esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN | in fsl_esdhc_init()
793 if (priv->vs18_enable) in fsl_esdhc_init()
794 esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT); in fsl_esdhc_init()
796 writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten); in fsl_esdhc_init()
797 cfg = &plat->cfg; in fsl_esdhc_init()
803 caps = esdhc_read32(&regs->hostcapblt); in fsl_esdhc_init()
822 cfg->name = "FSL_SDHC"; in fsl_esdhc_init()
824 cfg->ops = &esdhc_ops; in fsl_esdhc_init()
827 cfg->voltages = CONFIG_SYS_SD_VOLTAGE; in fsl_esdhc_init()
829 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; in fsl_esdhc_init()
831 if ((cfg->voltages & voltage_caps) == 0) { in fsl_esdhc_init()
833 return -1; in fsl_esdhc_init()
836 if (priv->bus_width == 8) in fsl_esdhc_init()
837 cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; in fsl_esdhc_init()
838 else if (priv->bus_width == 4) in fsl_esdhc_init()
839 cfg->host_caps = MMC_MODE_4BIT; in fsl_esdhc_init()
841 cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; in fsl_esdhc_init()
843 cfg->host_caps |= MMC_MODE_DDR_52MHz; in fsl_esdhc_init()
846 if (priv->bus_width > 0) { in fsl_esdhc_init()
847 if (priv->bus_width < 8) in fsl_esdhc_init()
848 cfg->host_caps &= ~MMC_MODE_8BIT; in fsl_esdhc_init()
849 if (priv->bus_width < 4) in fsl_esdhc_init()
850 cfg->host_caps &= ~MMC_MODE_4BIT; in fsl_esdhc_init()
854 cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; in fsl_esdhc_init()
858 cfg->host_caps &= ~MMC_MODE_8BIT; in fsl_esdhc_init()
861 cfg->f_min = 400000; in fsl_esdhc_init()
862 cfg->f_max = min(priv->sdhc_clk, (u32)52000000); in fsl_esdhc_init()
864 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; in fsl_esdhc_init()
874 return -EINVAL; in fsl_esdhc_cfg_to_priv()
876 priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base); in fsl_esdhc_cfg_to_priv()
877 priv->bus_width = cfg->max_bus_width; in fsl_esdhc_cfg_to_priv()
878 priv->sdhc_clk = cfg->sdhc_clk; in fsl_esdhc_cfg_to_priv()
879 priv->wp_enable = cfg->wp_enable; in fsl_esdhc_cfg_to_priv()
880 priv->vs18_enable = cfg->vs18_enable; in fsl_esdhc_cfg_to_priv()
893 return -EINVAL; in fsl_esdhc_initialize()
897 return -ENOMEM; in fsl_esdhc_initialize()
901 return -ENOMEM; in fsl_esdhc_initialize()
920 mmc = mmc_create(&plat->cfg, priv); in fsl_esdhc_initialize()
922 return -EIO; in fsl_esdhc_initialize()
924 priv->mmc = mmc; in fsl_esdhc_initialize()
934 cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR; in fsl_esdhc_mmc_init()
935 cfg->sdhc_clk = gd->arch.sdhc_clk; in fsl_esdhc_mmc_init()
947 gd->arch.sdhc_adapter = card_id; in mmc_adapter_card_type_ident()
1000 do_fixup_by_compat_u32(blob, compat, "peripheral-frequency", in fdt_fixup_esdhc()
1001 gd->arch.sdhc_clk, 1); in fdt_fixup_esdhc()
1003 do_fixup_by_compat_u32(blob, compat, "clock-frequency", in fdt_fixup_esdhc()
1004 gd->arch.sdhc_clk, 1); in fdt_fixup_esdhc()
1007 do_fixup_by_compat_u32(blob, compat, "adapter-type", in fdt_fixup_esdhc()
1008 (u32)(gd->arch.sdhc_adapter), 1); in fdt_fixup_esdhc()
1034 return -EINVAL; in fsl_esdhc_probe()
1036 priv->esdhc_regs = (struct fsl_esdhc *)addr; in fsl_esdhc_probe()
1037 priv->dev = dev; in fsl_esdhc_probe()
1039 val = dev_read_u32_default(dev, "bus-width", -1); in fsl_esdhc_probe()
1041 priv->bus_width = 8; in fsl_esdhc_probe()
1043 priv->bus_width = 4; in fsl_esdhc_probe()
1045 priv->bus_width = 1; in fsl_esdhc_probe()
1047 if (dev_read_bool(dev, "non-removable")) { in fsl_esdhc_probe()
1048 priv->non_removable = 1; in fsl_esdhc_probe()
1050 priv->non_removable = 0; in fsl_esdhc_probe()
1052 gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, in fsl_esdhc_probe()
1057 priv->wp_enable = 1; in fsl_esdhc_probe()
1060 ret = gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, in fsl_esdhc_probe()
1063 priv->wp_enable = 0; in fsl_esdhc_probe()
1066 priv->vs18_enable = 0; in fsl_esdhc_probe()
1073 ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev); in fsl_esdhc_probe()
1075 dev_dbg(dev, "no vqmmc-supply\n"); in fsl_esdhc_probe()
1079 dev_err(dev, "fail to enable vqmmc-supply\n"); in fsl_esdhc_probe()
1084 priv->vs18_enable = 1; in fsl_esdhc_probe()
1108 init_clk_usdhc(dev->seq); in fsl_esdhc_probe()
1110 priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq); in fsl_esdhc_probe()
1111 if (priv->sdhc_clk <= 0) { in fsl_esdhc_probe()
1112 dev_err(dev, "Unable to get clk for %s\n", dev->name); in fsl_esdhc_probe()
1113 return -EINVAL; in fsl_esdhc_probe()
1122 mmc = &plat->mmc; in fsl_esdhc_probe()
1123 mmc->cfg = &plat->cfg; in fsl_esdhc_probe()
1124 mmc->dev = dev; in fsl_esdhc_probe()
1125 upriv->mmc = mmc; in fsl_esdhc_probe()
1145 return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data); in fsl_esdhc_send_cmd()
1153 return esdhc_set_ios_common(priv, &plat->mmc); in fsl_esdhc_set_ios()
1164 { .compatible = "fsl,imx6ul-usdhc", },
1165 { .compatible = "fsl,imx6sx-usdhc", },
1166 { .compatible = "fsl,imx6sl-usdhc", },
1167 { .compatible = "fsl,imx6q-usdhc", },
1168 { .compatible = "fsl,imx7d-usdhc", },
1169 { .compatible = "fsl,imx7ulp-usdhc", },
1179 return mmc_bind(dev, &plat->mmc, &plat->cfg); in fsl_esdhc_bind()
1184 .name = "fsl-esdhc-mmc",