• Home
  • Raw
  • Download

Lines Matching +full:imx35 +full:- +full:esdhc

1 // SPDX-License-Identifier: GPL-2.0
3 * Freescale eSDHC i.MX controller driver for the platform bus.
5 * derived from the OF-version.
23 #include <linux/mmc/slot-gpio.h>
27 #include <linux/platform_data/mmc-esdhc-imx.h>
29 #include "sdhci-pltfm.h"
30 #include "sdhci-esdhc.h"
82 #define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1)
120 * There is an INT DMA ERR mismatch between eSDHC and STD SDHC SPEC:
121 * Bit25 is used in STD SPEC, and is reserved in fsl eSDHC design,
122 * but bit28 is used as the INT DMA ERR in fsl eSDHC design.
123 * Define this macro DMA error INT for fsl eSDHC
133 * open ended multi-blk IO. Otherwise the TC INT wouldn't
143 * The flag tells that the ESDHC controller is an USDHC block that is
299 .name = "sdhci-esdhc-imx25",
302 .name = "sdhci-esdhc-imx35",
305 .name = "sdhci-esdhc-imx51",
314 { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, },
315 { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
316 { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, },
317 { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, },
318 { .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
319 { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
320 { .compatible = "fsl,imx6sll-usdhc", .data = &usdhc_imx6sll_data, },
321 { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
322 { .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, },
323 { .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },
324 { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, },
325 { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, },
326 { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, },
333 return data->socdata == &esdhc_imx25_data; in is_imx25_esdhc()
338 return data->socdata == &esdhc_imx53_data; in is_imx53_esdhc()
343 return data->socdata == &usdhc_imx6q_data; in is_imx6q_usdhc()
348 return !!(data->socdata->flags & ESDHC_FLAG_USDHC); in esdhc_is_usdhc()
353 void __iomem *base = host->ioaddr + (reg & ~0x3); in esdhc_clrset_le()
359 #define DRIVER_NAME "sdhci-esdhc-imx"
361 pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
375 ESDHC_IMX_DUMP("========= ESDHC IMX DEBUG STATUS DUMP =========\n"); in esdhc_dump_debug_regs()
380 readw(host->ioaddr + ESDHC_DEBUG_SEL_AND_STATUS_REG)); in esdhc_dump_debug_regs()
392 ret = readl_poll_timeout(host->ioaddr + ESDHC_PRSSTAT, present_state, in esdhc_wait_for_card_clock_gate_off()
394 if (ret == -ETIMEDOUT) in esdhc_wait_for_card_clock_gate_off()
395 dev_warn(mmc_dev(host->mmc), "%s: card clock still not gate off in 100us!.\n", __func__); in esdhc_wait_for_card_clock_gate_off()
402 u32 val = readl(host->ioaddr + reg); in esdhc_readl_le()
408 /* move dat[0-3] bits */ in esdhc_readl_le()
415 /* ignore bit[0-15] as it stores cap_1 register val for mx6sl */ in esdhc_readl_le()
416 if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) in esdhc_readl_le()
419 /* In FSL esdhc IC module, only bit20 is used to indicate the in esdhc_readl_le()
420 * ADMA2 capability of esdhc, but this bit is messed up on in esdhc_readl_le()
434 if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) in esdhc_readl_le()
435 val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF; in esdhc_readl_le()
444 if (imx_data->socdata->flags & ESDHC_FLAG_HS400) in esdhc_readl_le()
451 if (IS_ERR_OR_NULL(imx_data->pins_100mhz) || in esdhc_readl_le()
452 IS_ERR_OR_NULL(imx_data->pins_200mhz)) in esdhc_readl_le()
475 if ((imx_data->multiblock_status == WAIT_FOR_INT) && in esdhc_readl_le()
478 writel(SDHCI_INT_RESPONSE, host->ioaddr + in esdhc_readl_le()
480 imx_data->multiblock_status = NO_CMD_PENDING; in esdhc_readl_le()
498 * card interrupt. This is an eSDHC controller problem in esdhc_writel_le()
500 * and set D3CD bit will make eSDHC re-sample the card in esdhc_writel_le()
502 * re-sample it by the following steps. in esdhc_writel_le()
504 data = readl(host->ioaddr + SDHCI_HOST_CONTROL); in esdhc_writel_le()
506 writel(data, host->ioaddr + SDHCI_HOST_CONTROL); in esdhc_writel_le()
508 writel(data, host->ioaddr + SDHCI_HOST_CONTROL); in esdhc_writel_le()
517 if (unlikely((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) in esdhc_writel_le()
521 v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writel_le()
523 writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writel_le()
525 if (imx_data->multiblock_status == MULTIBLK_IN_PROCESS) in esdhc_writel_le()
530 writel(data, host->ioaddr + SDHCI_TRANSFER_MODE); in esdhc_writel_le()
531 imx_data->multiblock_status = WAIT_FOR_INT; in esdhc_writel_le()
535 writel(val, host->ioaddr + reg); in esdhc_writel_le()
557 val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_readw_le()
562 if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) in esdhc_readw_le()
563 val = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_readw_le()
564 else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) in esdhc_readw_le()
566 val = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); in esdhc_readw_le()
581 u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_readw_le()
589 ret = readw(host->ioaddr + SDHCI_TRANSFER_MODE); in esdhc_readw_le()
595 return readw(host->ioaddr + reg); in esdhc_readw_le()
606 new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writew_le()
611 writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writew_le()
616 new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writew_le()
621 writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writew_le()
622 if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { in esdhc_writew_le()
623 new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writew_le()
631 writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writew_le()
632 } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { in esdhc_writew_le()
633 u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); in esdhc_writew_le()
634 u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writew_le()
651 writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); in esdhc_writew_le()
652 writel(m, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writew_le()
656 if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) in esdhc_writew_le()
657 && (host->cmd->opcode == SD_IO_RW_EXTENDED) in esdhc_writew_le()
658 && (host->cmd->data->blocks > 1) in esdhc_writew_le()
659 && (host->cmd->data->flags & MMC_DATA_READ)) { in esdhc_writew_le()
661 v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writew_le()
663 writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_writew_le()
668 u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writew_le()
675 writel(m, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writew_le()
681 m = readl(host->ioaddr + ESDHC_WTMK_LVL); in esdhc_writew_le()
704 writel(m, host->ioaddr + ESDHC_WTMK_LVL); in esdhc_writew_le()
710 imx_data->scratchpad = val; in esdhc_writew_le()
714 if (host->cmd->opcode == MMC_STOP_TRANSMISSION) in esdhc_writew_le()
717 if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) && in esdhc_writew_le()
718 (imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) in esdhc_writew_le()
719 imx_data->multiblock_status = MULTIBLK_IN_PROCESS; in esdhc_writew_le()
723 host->ioaddr + SDHCI_TRANSFER_MODE); in esdhc_writew_le()
725 writel(val << 16 | imx_data->scratchpad, in esdhc_writew_le()
726 host->ioaddr + SDHCI_TRANSFER_MODE); in esdhc_writew_le()
742 val = readl(host->ioaddr + reg); in esdhc_readb_le()
751 return readb(host->ioaddr + reg); in esdhc_readb_le()
791 new_val = readl(host->ioaddr + SDHCI_HOST_CONTROL); in esdhc_writeb_le()
799 * The esdhc has a design violation to SDHC spec which in esdhc_writeb_le()
801 * detection circuit. But esdhc clears its SYSCTL in esdhc_writeb_le()
816 new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writeb_le()
818 host->ioaddr + ESDHC_MIX_CTRL); in esdhc_writeb_le()
819 imx_data->is_ddr = 0; in esdhc_writeb_le()
823 * The eSDHC DAT line software reset clears at least the in esdhc_writeb_le()
837 return pltfm_host->clock; in esdhc_pltfm_get_max_clock()
844 return pltfm_host->clock / 256 / 16; in esdhc_pltfm_get_min_clock()
852 unsigned int host_clock = pltfm_host->clock; in esdhc_pltfm_set_clock()
853 int ddr_pre_div = imx_data->is_ddr ? 2 : 1; in esdhc_pltfm_set_clock()
860 val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_pltfm_set_clock()
862 host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_pltfm_set_clock()
867 host->mmc->actual_clock = 0; in esdhc_pltfm_set_clock()
877 val = readl(host->ioaddr + ESDHC_DLL_CTRL); in esdhc_pltfm_set_clock()
878 writel(val | BIT(10), host->ioaddr + ESDHC_DLL_CTRL); in esdhc_pltfm_set_clock()
879 temp = readl(host->ioaddr + ESDHC_DLL_CTRL); in esdhc_pltfm_set_clock()
880 writel(val, host->ioaddr + ESDHC_DLL_CTRL); in esdhc_pltfm_set_clock()
890 if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) { in esdhc_pltfm_set_clock()
893 max_clock = imx_data->is_ddr ? 45000000 : 150000000; in esdhc_pltfm_set_clock()
905 host->mmc->actual_clock = host_clock / (div * pre_div * ddr_pre_div); in esdhc_pltfm_set_clock()
906 dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", in esdhc_pltfm_set_clock()
907 clock, host->mmc->actual_clock); in esdhc_pltfm_set_clock()
910 div--; in esdhc_pltfm_set_clock()
919 ret = readl_poll_timeout(host->ioaddr + ESDHC_PRSSTAT, temp, in esdhc_pltfm_set_clock()
921 if (ret == -ETIMEDOUT) in esdhc_pltfm_set_clock()
922 dev_warn(mmc_dev(host->mmc), "card clock still not stable in 100us!.\n"); in esdhc_pltfm_set_clock()
925 val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_pltfm_set_clock()
927 host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_pltfm_set_clock()
936 struct esdhc_platform_data *boarddata = &imx_data->boarddata; in esdhc_pltfm_get_ro()
938 switch (boarddata->wp_type) { in esdhc_pltfm_get_ro()
940 return mmc_gpio_get_ro(host->mmc); in esdhc_pltfm_get_ro()
942 return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) & in esdhc_pltfm_get_ro()
948 return -ENOSYS; in esdhc_pltfm_get_ro()
979 if (host->timing == MMC_TIMING_UHS_DDR50) in usdhc_execute_tuning()
996 ret = readb_poll_timeout(host->ioaddr + SDHCI_SOFTWARE_RESET, sw_rst, in esdhc_prepare_tuning()
998 if (ret == -ETIMEDOUT) in esdhc_prepare_tuning()
999 dev_warn(mmc_dev(host->mmc), in esdhc_prepare_tuning()
1002 reg = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_prepare_tuning()
1005 writel(reg, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_prepare_tuning()
1006 writel(val << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); in esdhc_prepare_tuning()
1007 dev_dbg(mmc_dev(host->mmc), in esdhc_prepare_tuning()
1009 val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS)); in esdhc_prepare_tuning()
1016 reg = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_post_tuning()
1019 writel(reg, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_post_tuning()
1030 if (!mmc_send_tuning(host->mmc, opcode, NULL)) in esdhc_executing_tuning()
1039 if (mmc_send_tuning(host->mmc, opcode, NULL)) { in esdhc_executing_tuning()
1040 max -= ESDHC_TUNE_CTRL_STEP; in esdhc_executing_tuning()
1049 ret = mmc_send_tuning(host->mmc, opcode, NULL); in esdhc_executing_tuning()
1052 dev_dbg(mmc_dev(host->mmc), "tuning %s at 0x%x ret %d\n", in esdhc_executing_tuning()
1063 m = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_hs400_enhanced_strobe()
1064 if (ios->enhanced_strobe) in esdhc_hs400_enhanced_strobe()
1068 writel(m, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_hs400_enhanced_strobe()
1078 dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs); in esdhc_change_pinstate()
1080 if (IS_ERR(imx_data->pinctrl) || in esdhc_change_pinstate()
1081 IS_ERR(imx_data->pins_100mhz) || in esdhc_change_pinstate()
1082 IS_ERR(imx_data->pins_200mhz)) in esdhc_change_pinstate()
1083 return -EINVAL; in esdhc_change_pinstate()
1088 pinctrl = imx_data->pins_100mhz; in esdhc_change_pinstate()
1093 pinctrl = imx_data->pins_200mhz; in esdhc_change_pinstate()
1097 return pinctrl_select_default_state(mmc_dev(host->mmc)); in esdhc_change_pinstate()
1100 return pinctrl_select_state(imx_data->pinctrl, pinctrl); in esdhc_change_pinstate()
1121 writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) & in esdhc_set_strobe_dll()
1123 host->ioaddr + ESDHC_VENDOR_SPEC); in esdhc_set_strobe_dll()
1128 host->ioaddr + ESDHC_STROBE_DLL_CTRL); in esdhc_set_strobe_dll()
1130 writel(0, host->ioaddr + ESDHC_STROBE_DLL_CTRL); in esdhc_set_strobe_dll()
1136 if (imx_data->boarddata.strobe_dll_delay_target) in esdhc_set_strobe_dll()
1137 strobe_delay = imx_data->boarddata.strobe_dll_delay_target; in esdhc_set_strobe_dll()
1143 writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); in esdhc_set_strobe_dll()
1146 ret = readl_poll_timeout(host->ioaddr + ESDHC_STROBE_DLL_STATUS, v, in esdhc_set_strobe_dll()
1148 if (ret == -ETIMEDOUT) in esdhc_set_strobe_dll()
1149 dev_warn(mmc_dev(host->mmc), in esdhc_set_strobe_dll()
1162 if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { in esdhc_reset_tuning()
1163 ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_reset_tuning()
1166 writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_reset_tuning()
1167 writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); in esdhc_reset_tuning()
1168 } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { in esdhc_reset_tuning()
1169 ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); in esdhc_reset_tuning()
1172 writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS); in esdhc_reset_tuning()
1174 ret = readl_poll_timeout(host->ioaddr + SDHCI_AUTO_CMD_STATUS, in esdhc_reset_tuning()
1176 if (ret == -ETIMEDOUT) in esdhc_reset_tuning()
1177 dev_warn(mmc_dev(host->mmc), in esdhc_reset_tuning()
1184 ctrl = readl(host->ioaddr + SDHCI_INT_STATUS); in esdhc_reset_tuning()
1186 writel(ctrl, host->ioaddr + SDHCI_INT_STATUS); in esdhc_reset_tuning()
1196 struct esdhc_platform_data *boarddata = &imx_data->boarddata; in esdhc_set_uhs_signaling()
1199 m = readl(host->ioaddr + ESDHC_MIX_CTRL); in esdhc_set_uhs_signaling()
1201 imx_data->is_ddr = 0; in esdhc_set_uhs_signaling()
1210 writel(m, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_set_uhs_signaling()
1215 writel(m, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_set_uhs_signaling()
1216 imx_data->is_ddr = 1; in esdhc_set_uhs_signaling()
1217 if (boarddata->delay_line) { in esdhc_set_uhs_signaling()
1219 v = boarddata->delay_line << in esdhc_set_uhs_signaling()
1224 writel(v, host->ioaddr + ESDHC_DLL_CTRL); in esdhc_set_uhs_signaling()
1229 writel(m, host->ioaddr + ESDHC_MIX_CTRL); in esdhc_set_uhs_signaling()
1230 imx_data->is_ddr = 1; in esdhc_set_uhs_signaling()
1232 host->ops->set_clock(host, host->clock); in esdhc_set_uhs_signaling()
1248 sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); in esdhc_reset()
1249 sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); in esdhc_reset()
1280 cqhci_irq(host->mmc, intmask, cmd_error, data_error); in esdhc_cqhci_irq()
1317 struct cqhci_host *cq_host = host->mmc->cqe_private; in sdhci_esdhc_imx_hwinit()
1325 writel(ESDHC_WTMK_DEFAULT_VAL, host->ioaddr + ESDHC_WTMK_LVL); in sdhci_esdhc_imx_hwinit()
1338 writel(readl(host->ioaddr + SDHCI_HOST_CONTROL) in sdhci_esdhc_imx_hwinit()
1340 host->ioaddr + SDHCI_HOST_CONTROL); in sdhci_esdhc_imx_hwinit()
1346 writel(readl(host->ioaddr + 0x6c) & ~BIT(7), in sdhci_esdhc_imx_hwinit()
1347 host->ioaddr + 0x6c); in sdhci_esdhc_imx_hwinit()
1350 writel(0x0, host->ioaddr + ESDHC_DLL_CTRL); in sdhci_esdhc_imx_hwinit()
1361 if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { in sdhci_esdhc_imx_hwinit()
1362 tmp = readl(host->ioaddr + ESDHC_VEND_SPEC2); in sdhci_esdhc_imx_hwinit()
1364 writel(tmp, host->ioaddr + ESDHC_VEND_SPEC2); in sdhci_esdhc_imx_hwinit()
1366 host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; in sdhci_esdhc_imx_hwinit()
1369 if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { in sdhci_esdhc_imx_hwinit()
1370 tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); in sdhci_esdhc_imx_hwinit()
1373 if (imx_data->boarddata.tuning_start_tap) { in sdhci_esdhc_imx_hwinit()
1375 tmp |= imx_data->boarddata.tuning_start_tap; in sdhci_esdhc_imx_hwinit()
1378 if (imx_data->boarddata.tuning_step) { in sdhci_esdhc_imx_hwinit()
1380 tmp |= imx_data->boarddata.tuning_step in sdhci_esdhc_imx_hwinit()
1395 writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); in sdhci_esdhc_imx_hwinit()
1396 } else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { in sdhci_esdhc_imx_hwinit()
1402 tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); in sdhci_esdhc_imx_hwinit()
1404 writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); in sdhci_esdhc_imx_hwinit()
1427 struct cqhci_host *cq_host = mmc->cqe_private; in esdhc_cqe_enable()
1440 if (count-- == 0) { in esdhc_cqe_enable()
1441 dev_warn(mmc_dev(host->mmc), in esdhc_cqe_enable()
1454 if (host->flags & SDHCI_REQ_USE_DMA) in esdhc_cqe_enable()
1456 if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) in esdhc_cqe_enable()
1468 dev_err(mmc_dev(host->mmc), in esdhc_cqe_enable()
1492 struct device_node *np = pdev->dev.of_node; in sdhci_esdhc_imx_probe_dt()
1493 struct esdhc_platform_data *boarddata = &imx_data->boarddata; in sdhci_esdhc_imx_probe_dt()
1496 if (of_get_property(np, "fsl,wp-controller", NULL)) in sdhci_esdhc_imx_probe_dt()
1497 boarddata->wp_type = ESDHC_WP_CONTROLLER; in sdhci_esdhc_imx_probe_dt()
1504 if (of_property_read_bool(np, "wp-gpios")) in sdhci_esdhc_imx_probe_dt()
1505 boarddata->wp_type = ESDHC_WP_GPIO; in sdhci_esdhc_imx_probe_dt()
1507 of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); in sdhci_esdhc_imx_probe_dt()
1508 of_property_read_u32(np, "fsl,tuning-start-tap", in sdhci_esdhc_imx_probe_dt()
1509 &boarddata->tuning_start_tap); in sdhci_esdhc_imx_probe_dt()
1511 of_property_read_u32(np, "fsl,strobe-dll-delay-target", in sdhci_esdhc_imx_probe_dt()
1512 &boarddata->strobe_dll_delay_target); in sdhci_esdhc_imx_probe_dt()
1513 if (of_find_property(np, "no-1-8-v", NULL)) in sdhci_esdhc_imx_probe_dt()
1514 host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; in sdhci_esdhc_imx_probe_dt()
1516 if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) in sdhci_esdhc_imx_probe_dt()
1517 boarddata->delay_line = 0; in sdhci_esdhc_imx_probe_dt()
1519 mmc_of_parse_voltage(np, &host->ocr_mask); in sdhci_esdhc_imx_probe_dt()
1521 if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pinctrl)) { in sdhci_esdhc_imx_probe_dt()
1522 imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, in sdhci_esdhc_imx_probe_dt()
1524 imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, in sdhci_esdhc_imx_probe_dt()
1529 ret = mmc_of_parse(host->mmc); in sdhci_esdhc_imx_probe_dt()
1533 if (mmc_gpio_get_cd(host->mmc) >= 0) in sdhci_esdhc_imx_probe_dt()
1534 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; in sdhci_esdhc_imx_probe_dt()
1544 return -ENODEV; in sdhci_esdhc_imx_probe_dt()
1552 struct esdhc_platform_data *boarddata = &imx_data->boarddata; in sdhci_esdhc_imx_probe_nondt()
1555 if (!host->mmc->parent->platform_data) { in sdhci_esdhc_imx_probe_nondt()
1556 dev_err(mmc_dev(host->mmc), "no board data!\n"); in sdhci_esdhc_imx_probe_nondt()
1557 return -EINVAL; in sdhci_esdhc_imx_probe_nondt()
1560 imx_data->boarddata = *((struct esdhc_platform_data *) in sdhci_esdhc_imx_probe_nondt()
1561 host->mmc->parent->platform_data); in sdhci_esdhc_imx_probe_nondt()
1563 if (boarddata->wp_type == ESDHC_WP_GPIO) { in sdhci_esdhc_imx_probe_nondt()
1564 host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; in sdhci_esdhc_imx_probe_nondt()
1566 err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0); in sdhci_esdhc_imx_probe_nondt()
1568 dev_err(mmc_dev(host->mmc), in sdhci_esdhc_imx_probe_nondt()
1569 "failed to request write-protect gpio!\n"); in sdhci_esdhc_imx_probe_nondt()
1575 switch (boarddata->cd_type) { in sdhci_esdhc_imx_probe_nondt()
1577 err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0); in sdhci_esdhc_imx_probe_nondt()
1579 dev_err(mmc_dev(host->mmc), in sdhci_esdhc_imx_probe_nondt()
1580 "failed to request card-detect gpio!\n"); in sdhci_esdhc_imx_probe_nondt()
1587 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; in sdhci_esdhc_imx_probe_nondt()
1591 host->mmc->caps |= MMC_CAP_NONREMOVABLE; in sdhci_esdhc_imx_probe_nondt()
1598 switch (boarddata->max_bus_width) { in sdhci_esdhc_imx_probe_nondt()
1600 host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; in sdhci_esdhc_imx_probe_nondt()
1603 host->mmc->caps |= MMC_CAP_4_BIT_DATA; in sdhci_esdhc_imx_probe_nondt()
1607 host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; in sdhci_esdhc_imx_probe_nondt()
1617 of_match_device(imx_esdhc_dt_ids, &pdev->dev); in sdhci_esdhc_imx_probe()
1633 imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *) in sdhci_esdhc_imx_probe()
1634 pdev->id_entry->driver_data; in sdhci_esdhc_imx_probe()
1636 if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) in sdhci_esdhc_imx_probe()
1637 cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); in sdhci_esdhc_imx_probe()
1639 imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); in sdhci_esdhc_imx_probe()
1640 if (IS_ERR(imx_data->clk_ipg)) { in sdhci_esdhc_imx_probe()
1641 err = PTR_ERR(imx_data->clk_ipg); in sdhci_esdhc_imx_probe()
1645 imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); in sdhci_esdhc_imx_probe()
1646 if (IS_ERR(imx_data->clk_ahb)) { in sdhci_esdhc_imx_probe()
1647 err = PTR_ERR(imx_data->clk_ahb); in sdhci_esdhc_imx_probe()
1651 imx_data->clk_per = devm_clk_get(&pdev->dev, "per"); in sdhci_esdhc_imx_probe()
1652 if (IS_ERR(imx_data->clk_per)) { in sdhci_esdhc_imx_probe()
1653 err = PTR_ERR(imx_data->clk_per); in sdhci_esdhc_imx_probe()
1657 pltfm_host->clk = imx_data->clk_per; in sdhci_esdhc_imx_probe()
1658 pltfm_host->clock = clk_get_rate(pltfm_host->clk); in sdhci_esdhc_imx_probe()
1659 err = clk_prepare_enable(imx_data->clk_per); in sdhci_esdhc_imx_probe()
1662 err = clk_prepare_enable(imx_data->clk_ipg); in sdhci_esdhc_imx_probe()
1665 err = clk_prepare_enable(imx_data->clk_ahb); in sdhci_esdhc_imx_probe()
1669 imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); in sdhci_esdhc_imx_probe()
1670 if (IS_ERR(imx_data->pinctrl)) in sdhci_esdhc_imx_probe()
1671 dev_warn(mmc_dev(host->mmc), "could not get pinctrl\n"); in sdhci_esdhc_imx_probe()
1674 host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; in sdhci_esdhc_imx_probe()
1675 host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; in sdhci_esdhc_imx_probe()
1678 host->mmc->caps |= MMC_CAP_CD_WAKE; in sdhci_esdhc_imx_probe()
1680 if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200)) in sdhci_esdhc_imx_probe()
1681 host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; in sdhci_esdhc_imx_probe()
1684 writel(0x0, host->ioaddr + ESDHC_MIX_CTRL); in sdhci_esdhc_imx_probe()
1685 writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS); in sdhci_esdhc_imx_probe()
1686 writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); in sdhci_esdhc_imx_probe()
1692 host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; in sdhci_esdhc_imx_probe()
1695 if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) in sdhci_esdhc_imx_probe()
1699 if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) in sdhci_esdhc_imx_probe()
1700 host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; in sdhci_esdhc_imx_probe()
1702 if (imx_data->socdata->flags & ESDHC_FLAG_HS400) in sdhci_esdhc_imx_probe()
1703 host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; in sdhci_esdhc_imx_probe()
1705 if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) in sdhci_esdhc_imx_probe()
1706 host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; in sdhci_esdhc_imx_probe()
1708 if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { in sdhci_esdhc_imx_probe()
1709 host->mmc->caps2 |= MMC_CAP2_HS400_ES; in sdhci_esdhc_imx_probe()
1710 host->mmc_host_ops.hs400_enhanced_strobe = in sdhci_esdhc_imx_probe()
1714 if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { in sdhci_esdhc_imx_probe()
1715 host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; in sdhci_esdhc_imx_probe()
1716 cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL); in sdhci_esdhc_imx_probe()
1718 err = -ENOMEM; in sdhci_esdhc_imx_probe()
1722 cq_host->mmio = host->ioaddr + ESDHC_CQHCI_ADDR_OFFSET; in sdhci_esdhc_imx_probe()
1723 cq_host->ops = &esdhc_cqhci_ops; in sdhci_esdhc_imx_probe()
1725 err = cqhci_init(cq_host, host->mmc, false); in sdhci_esdhc_imx_probe()
1743 pm_runtime_set_active(&pdev->dev); in sdhci_esdhc_imx_probe()
1744 pm_runtime_set_autosuspend_delay(&pdev->dev, 50); in sdhci_esdhc_imx_probe()
1745 pm_runtime_use_autosuspend(&pdev->dev); in sdhci_esdhc_imx_probe()
1746 pm_suspend_ignore_children(&pdev->dev, 1); in sdhci_esdhc_imx_probe()
1747 pm_runtime_enable(&pdev->dev); in sdhci_esdhc_imx_probe()
1752 clk_disable_unprepare(imx_data->clk_ahb); in sdhci_esdhc_imx_probe()
1754 clk_disable_unprepare(imx_data->clk_ipg); in sdhci_esdhc_imx_probe()
1756 clk_disable_unprepare(imx_data->clk_per); in sdhci_esdhc_imx_probe()
1758 if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) in sdhci_esdhc_imx_probe()
1759 cpu_latency_qos_remove_request(&imx_data->pm_qos_req); in sdhci_esdhc_imx_probe()
1771 pm_runtime_get_sync(&pdev->dev); in sdhci_esdhc_imx_remove()
1772 dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); in sdhci_esdhc_imx_remove()
1773 pm_runtime_disable(&pdev->dev); in sdhci_esdhc_imx_remove()
1774 pm_runtime_put_noidle(&pdev->dev); in sdhci_esdhc_imx_remove()
1778 clk_disable_unprepare(imx_data->clk_per); in sdhci_esdhc_imx_remove()
1779 clk_disable_unprepare(imx_data->clk_ipg); in sdhci_esdhc_imx_remove()
1780 clk_disable_unprepare(imx_data->clk_ahb); in sdhci_esdhc_imx_remove()
1782 if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) in sdhci_esdhc_imx_remove()
1783 cpu_latency_qos_remove_request(&imx_data->pm_qos_req); in sdhci_esdhc_imx_remove()
1798 if (host->mmc->caps2 & MMC_CAP2_CQE) { in sdhci_esdhc_suspend()
1799 ret = cqhci_suspend(host->mmc); in sdhci_esdhc_suspend()
1804 if ((imx_data->socdata->flags & ESDHC_FLAG_STATE_LOST_IN_LPMODE) && in sdhci_esdhc_suspend()
1805 (host->tuning_mode != SDHCI_TUNING_MODE_1)) { in sdhci_esdhc_suspend()
1806 mmc_retune_timer_stop(host->mmc); in sdhci_esdhc_suspend()
1807 mmc_retune_needed(host->mmc); in sdhci_esdhc_suspend()
1810 if (host->tuning_mode != SDHCI_TUNING_MODE_3) in sdhci_esdhc_suspend()
1811 mmc_retune_needed(host->mmc); in sdhci_esdhc_suspend()
1821 ret = mmc_gpio_set_cd_wake(host->mmc, true); in sdhci_esdhc_suspend()
1835 /* re-initialize hw state in case it's lost in low power mode */ in sdhci_esdhc_resume()
1842 if (host->mmc->caps2 & MMC_CAP2_CQE) in sdhci_esdhc_resume()
1843 ret = cqhci_resume(host->mmc); in sdhci_esdhc_resume()
1846 ret = mmc_gpio_set_cd_wake(host->mmc, false); in sdhci_esdhc_resume()
1860 if (host->mmc->caps2 & MMC_CAP2_CQE) { in sdhci_esdhc_runtime_suspend()
1861 ret = cqhci_suspend(host->mmc); in sdhci_esdhc_runtime_suspend()
1870 if (host->tuning_mode != SDHCI_TUNING_MODE_3) in sdhci_esdhc_runtime_suspend()
1871 mmc_retune_needed(host->mmc); in sdhci_esdhc_runtime_suspend()
1873 imx_data->actual_clock = host->mmc->actual_clock; in sdhci_esdhc_runtime_suspend()
1875 clk_disable_unprepare(imx_data->clk_per); in sdhci_esdhc_runtime_suspend()
1876 clk_disable_unprepare(imx_data->clk_ipg); in sdhci_esdhc_runtime_suspend()
1877 clk_disable_unprepare(imx_data->clk_ahb); in sdhci_esdhc_runtime_suspend()
1879 if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) in sdhci_esdhc_runtime_suspend()
1880 cpu_latency_qos_remove_request(&imx_data->pm_qos_req); in sdhci_esdhc_runtime_suspend()
1892 if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) in sdhci_esdhc_runtime_resume()
1893 cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); in sdhci_esdhc_runtime_resume()
1895 if (imx_data->socdata->flags & ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME) in sdhci_esdhc_runtime_resume()
1896 clk_set_rate(imx_data->clk_per, pltfm_host->clock); in sdhci_esdhc_runtime_resume()
1898 err = clk_prepare_enable(imx_data->clk_ahb); in sdhci_esdhc_runtime_resume()
1902 err = clk_prepare_enable(imx_data->clk_per); in sdhci_esdhc_runtime_resume()
1906 err = clk_prepare_enable(imx_data->clk_ipg); in sdhci_esdhc_runtime_resume()
1910 esdhc_pltfm_set_clock(host, imx_data->actual_clock); in sdhci_esdhc_runtime_resume()
1916 if (host->mmc->caps2 & MMC_CAP2_CQE) in sdhci_esdhc_runtime_resume()
1917 err = cqhci_resume(host->mmc); in sdhci_esdhc_runtime_resume()
1922 clk_disable_unprepare(imx_data->clk_ipg); in sdhci_esdhc_runtime_resume()
1924 clk_disable_unprepare(imx_data->clk_per); in sdhci_esdhc_runtime_resume()
1926 clk_disable_unprepare(imx_data->clk_ahb); in sdhci_esdhc_runtime_resume()
1928 if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) in sdhci_esdhc_runtime_resume()
1929 cpu_latency_qos_remove_request(&imx_data->pm_qos_req); in sdhci_esdhc_runtime_resume()
1942 .name = "sdhci-esdhc-imx",
1954 MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");