Lines Matching +full:re +full:- +full:tuning
1 // SPDX-License-Identifier: GPL-2.0-or-later
22 #include <linux/dma-mapping.h>
26 #include "sdhci-pltfm.h"
27 #include "sdhci-esdhc.h"
71 { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk},
72 { .compatible = "fsl,ls1043a-esdhc", .data = &ls1043a_esdhc_clk},
73 { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk},
74 { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk},
75 { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk},
76 { .compatible = "fsl,mpc8379-esdhc" },
77 { .compatible = "fsl,mpc8536-esdhc" },
101 * esdhc_readl_fixup - Fixup the value read from incompatible eSDHC register
131 if (esdhc->vendor_ver > VENDOR_V_22) { in esdhc_readl_fixup()
156 if (esdhc->quirk_ignore_data_inhibit) in esdhc_readl_fixup()
185 return pltfm_host->xfer_mode_shadow; in esdhc_readw_fixup()
191 /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect in esdhc_readw_fixup()
195 (esdhc->quirk_incorrect_hostver)) in esdhc_readw_fixup()
224 * esdhc_writel_fixup - Fixup the SD spec register value so that it could be
270 pltfm_host->xfer_mode_shadow = value; in esdhc_writew_fixup()
273 ret = (value << 16) | pltfm_host->xfer_mode_shadow; in esdhc_writew_fixup()
283 * non-standard blksz of 4096 bytes that we don't support in esdhc_writew_fixup()
314 if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) in esdhc_writeb_fixup()
339 value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); in esdhc_be_readl()
341 value = ioread32be(host->ioaddr + reg); in esdhc_be_readl()
354 value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); in esdhc_le_readl()
356 value = ioread32(host->ioaddr + reg); in esdhc_le_readl()
369 value = ioread32be(host->ioaddr + base); in esdhc_be_readw()
380 value = ioread32(host->ioaddr + base); in esdhc_le_readw()
391 value = ioread32be(host->ioaddr + base); in esdhc_be_readb()
402 value = ioread32(host->ioaddr + base); in esdhc_le_readb()
412 iowrite32be(value, host->ioaddr + reg); in esdhc_be_writel()
420 iowrite32(value, host->ioaddr + reg); in esdhc_le_writel()
431 value = ioread32be(host->ioaddr + base); in esdhc_be_writew()
434 iowrite32be(ret, host->ioaddr + base); in esdhc_be_writew()
436 /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set in esdhc_be_writew()
441 esdhc->in_sw_tuning) { in esdhc_be_writew()
444 iowrite32be(ret, host->ioaddr + base); in esdhc_be_writew()
457 value = ioread32(host->ioaddr + base); in esdhc_le_writew()
460 iowrite32(ret, host->ioaddr + base); in esdhc_le_writew()
462 /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set in esdhc_le_writew()
467 esdhc->in_sw_tuning) { in esdhc_le_writew()
470 iowrite32(ret, host->ioaddr + base); in esdhc_le_writew()
481 value = ioread32be(host->ioaddr + base); in esdhc_be_writeb()
483 iowrite32be(ret, host->ioaddr + base); in esdhc_be_writeb()
492 value = ioread32(host->ioaddr + base); in esdhc_le_writeb()
494 iowrite32(ret, host->ioaddr + base); in esdhc_le_writeb()
502 * and re-issue the entire read transaction from beginning.
514 (esdhc->vendor_ver == VENDOR_V_23); in esdhc_of_adma_workaround()
518 host->data->error = 0; in esdhc_of_adma_workaround()
519 dmastart = sg_dma_address(host->data->sg); in esdhc_of_adma_workaround()
520 dmanow = dmastart + host->data->bytes_xfered; in esdhc_of_adma_workaround()
524 dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + in esdhc_of_adma_workaround()
526 host->data->bytes_xfered = dmanow - dmastart; in esdhc_of_adma_workaround()
534 struct device *dev = mmc_dev(host->mmc); in esdhc_of_enable_dma()
536 if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || in esdhc_of_enable_dma()
537 of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) { in esdhc_of_enable_dma()
545 if (of_dma_is_coherent(dev->of_node)) in esdhc_of_enable_dma()
559 if (esdhc->peripheral_clock) in esdhc_of_get_max_clock()
560 return esdhc->peripheral_clock; in esdhc_of_get_max_clock()
562 return pltfm_host->clock; in esdhc_of_get_max_clock()
571 if (esdhc->peripheral_clock) in esdhc_of_get_min_clock()
572 clock = esdhc->peripheral_clock; in esdhc_of_get_min_clock()
574 clock = pltfm_host->clock; in esdhc_of_get_min_clock()
591 if (esdhc->vendor_ver <= VENDOR_V_22) in esdhc_clock_enable()
609 while (esdhc->vendor_ver > VENDOR_V_22) { in esdhc_clock_enable()
616 mmc_hostname(host->mmc)); in esdhc_clock_enable()
642 mmc_hostname(host->mmc)); in esdhc_flush_async_fifo()
659 host->mmc->actual_clock = 0; in esdhc_of_set_clock()
665 if (esdhc->vendor_ver < VENDOR_V_23) in esdhc_of_set_clock()
669 if (host->mmc->card && mmc_card_sd(host->mmc->card) && in esdhc_of_set_clock()
670 esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) in esdhc_of_set_clock()
671 clock_fixup = esdhc->clk_fixup->sd_dflt_max_clk; in esdhc_of_set_clock()
672 else if (esdhc->clk_fixup) in esdhc_of_set_clock()
673 clock_fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; in esdhc_of_set_clock()
679 while (host->max_clk / pre_div / 16 > clock_fixup && pre_div < 256) in esdhc_of_set_clock()
682 while (host->max_clk / pre_div / div > clock_fixup && div < 16) in esdhc_of_set_clock()
685 esdhc->div_ratio = pre_div * div; in esdhc_of_set_clock()
688 if (esdhc->quirk_limited_clk_division && in esdhc_of_set_clock()
690 (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || in esdhc_of_set_clock()
691 host->flags & SDHCI_HS400_TUNING)) { in esdhc_of_set_clock()
692 if (esdhc->div_ratio <= 4) { in esdhc_of_set_clock()
695 } else if (esdhc->div_ratio <= 8) { in esdhc_of_set_clock()
698 } else if (esdhc->div_ratio <= 12) { in esdhc_of_set_clock()
703 mmc_hostname(host->mmc)); in esdhc_of_set_clock()
705 esdhc->div_ratio = pre_div * div; in esdhc_of_set_clock()
708 host->mmc->actual_clock = host->max_clk / esdhc->div_ratio; in esdhc_of_set_clock()
710 dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", in esdhc_of_set_clock()
711 clock, host->mmc->actual_clock); in esdhc_of_set_clock()
715 div--; in esdhc_of_set_clock()
730 while (esdhc->vendor_ver > VENDOR_V_22) { in esdhc_of_set_clock()
737 mmc_hostname(host->mmc)); in esdhc_of_set_clock()
744 if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && in esdhc_of_set_clock()
754 if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) in esdhc_of_set_clock()
770 mmc_hostname(host->mmc)); in esdhc_of_set_clock()
813 if (esdhc->quirk_delay_before_data_reset && in esdhc_reset()
815 (host->flags & SDHCI_REQ_USE_DMA)) in esdhc_reset()
819 * Save bus-width for eSDHC whose vendor version is 2.2 in esdhc_reset()
823 (esdhc->vendor_ver <= VENDOR_V_22)) { in esdhc_reset()
831 * Restore bus-width setting and interrupt registers for eSDHC in esdhc_reset()
835 (esdhc->vendor_ver <= VENDOR_V_22)) { in esdhc_reset()
841 sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); in esdhc_reset()
842 sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); in esdhc_reset()
850 (esdhc->spec_ver >= SDHCI_SPEC_300)) { in esdhc_reset()
859 if (esdhc->quirk_unreliable_pulse_detection) { in esdhc_reset()
873 { .compatible = "fsl,t1040-scfg", },
874 { .compatible = "fsl,ls1012a-scfg", },
875 { .compatible = "fsl,ls1046a-scfg", },
898 if (host->version < SDHCI_SPEC_300) in esdhc_signal_voltage_switch()
903 switch (ios->signal_voltage) { in esdhc_signal_voltage_switch()
1007 if (esdhc->quirk_tuning_erratum_type1) { in esdhc_prepare_sw_tuning()
1008 *window_start = 5 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1009 *window_end = 3 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1020 /* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 in esdhc_prepare_sw_tuning()
1021 * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2, in esdhc_prepare_sw_tuning()
1026 if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) { in esdhc_prepare_sw_tuning()
1027 *window_start = 8 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1028 *window_end = 4 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1030 *window_start = 5 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1031 *window_end = 3 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1050 /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ in esdhc_execute_sw_tuning()
1056 esdhc->in_sw_tuning = true; in esdhc_execute_sw_tuning()
1058 esdhc->in_sw_tuning = false; in esdhc_execute_sw_tuning()
1073 /* For tuning mode, the sd clock divisor value in esdhc_execute_tuning()
1076 clk = esdhc->peripheral_clock / 3; in esdhc_execute_tuning()
1077 if (host->clock > clk) in esdhc_execute_tuning()
1084 * during tuning. If the SD card is too slow sending the response, the in esdhc_execute_tuning()
1086 * is triggered. This leads to tuning errors. in esdhc_execute_tuning()
1093 hs400_tuning = host->flags & SDHCI_HS400_TUNING; in esdhc_execute_tuning()
1096 if (esdhc->quirk_limited_clk_division && in esdhc_execute_tuning()
1098 esdhc_of_set_clock(host, host->clock); in esdhc_execute_tuning()
1100 /* Do HW tuning */ in esdhc_execute_tuning()
1110 /* For type2 affected platforms of the tuning erratum, in esdhc_execute_tuning()
1111 * tuning may succeed although eSDHC might not have in esdhc_execute_tuning()
1112 * tuned properly. Need to check tuning window. in esdhc_execute_tuning()
1114 if (esdhc->quirk_tuning_erratum_type2 && in esdhc_execute_tuning()
1115 !host->tuning_err) { in esdhc_execute_tuning()
1118 if (abs(window_start - window_end) > in esdhc_execute_tuning()
1119 (4 * esdhc->div_ratio + 2)) in esdhc_execute_tuning()
1120 host->tuning_err = -EAGAIN; in esdhc_execute_tuning()
1123 /* If HW tuning fails and triggers erratum, in esdhc_execute_tuning()
1126 ret = host->tuning_err; in esdhc_execute_tuning()
1127 if (ret == -EAGAIN && in esdhc_execute_tuning()
1128 (esdhc->quirk_tuning_erratum_type1 || in esdhc_execute_tuning()
1129 esdhc->quirk_tuning_erratum_type2)) { in esdhc_execute_tuning()
1130 /* Recover HS400 tuning flag */ in esdhc_execute_tuning()
1132 host->flags |= SDHCI_HS400_TUNING; in esdhc_execute_tuning()
1133 pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", in esdhc_execute_tuning()
1135 /* Do SW tuning */ in esdhc_execute_tuning()
1144 /* Retry both HW/SW tuning with reduced clock. */ in esdhc_execute_tuning()
1145 ret = host->tuning_err; in esdhc_execute_tuning()
1146 if (ret == -EAGAIN && retries) { in esdhc_execute_tuning()
1147 /* Recover HS400 tuning flag */ in esdhc_execute_tuning()
1149 host->flags |= SDHCI_HS400_TUNING; in esdhc_execute_tuning()
1151 clk = host->max_clk / (esdhc->div_ratio + 1); in esdhc_execute_tuning()
1153 pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", in esdhc_execute_tuning()
1161 } while (retries--); in esdhc_execute_tuning()
1182 * exit HS400 mode before re-setting any speed mode. in esdhc_set_uhs_signaling()
1223 if (esdhc->quirk_trans_complete_erratum) { in esdhc_irq()
1245 if (host->tuning_mode != SDHCI_TUNING_MODE_3) in esdhc_of_suspend()
1246 mmc_retune_needed(host->mmc); in esdhc_of_suspend()
1257 /* Isn't this already done by sdhci_resume_host() ? --rmk */ in esdhc_of_resume()
1356 esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> in esdhc_init()
1358 esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; in esdhc_init()
1360 esdhc->quirk_incorrect_hostver = true; in esdhc_init()
1362 esdhc->quirk_incorrect_hostver = false; in esdhc_init()
1365 esdhc->quirk_limited_clk_division = true; in esdhc_init()
1367 esdhc->quirk_limited_clk_division = false; in esdhc_init()
1370 esdhc->quirk_unreliable_pulse_detection = true; in esdhc_init()
1372 esdhc->quirk_unreliable_pulse_detection = false; in esdhc_init()
1374 match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); in esdhc_init()
1376 esdhc->clk_fixup = match->data; in esdhc_init()
1377 np = pdev->dev.of_node; in esdhc_init()
1379 if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { in esdhc_init()
1380 esdhc->quirk_delay_before_data_reset = true; in esdhc_init()
1381 esdhc->quirk_trans_complete_erratum = true; in esdhc_init()
1387 * esdhc->peripheral_clock would be assigned with a value in esdhc_init()
1393 if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || in esdhc_init()
1394 of_device_is_compatible(np, "fsl,ls1028a-esdhc") || in esdhc_init()
1395 of_device_is_compatible(np, "fsl,ls1088a-esdhc")) in esdhc_init()
1396 esdhc->peripheral_clock = clk_get_rate(clk) / 2; in esdhc_init()
1398 esdhc->peripheral_clock = clk_get_rate(clk); in esdhc_init()
1410 if (esdhc->peripheral_clock) in esdhc_init()
1432 np = pdev->dev.of_node; in sdhci_esdhc_probe()
1434 if (of_property_read_bool(np, "little-endian")) in sdhci_esdhc_probe()
1444 host->mmc_host_ops.start_signal_voltage_switch = in sdhci_esdhc_probe()
1446 host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; in sdhci_esdhc_probe()
1447 host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; in sdhci_esdhc_probe()
1448 host->tuning_delay = 1; in sdhci_esdhc_probe()
1457 esdhc->quirk_tuning_erratum_type1 = true; in sdhci_esdhc_probe()
1459 esdhc->quirk_tuning_erratum_type1 = false; in sdhci_esdhc_probe()
1462 esdhc->quirk_tuning_erratum_type2 = true; in sdhci_esdhc_probe()
1464 esdhc->quirk_tuning_erratum_type2 = false; in sdhci_esdhc_probe()
1466 if (esdhc->vendor_ver == VENDOR_V_22) in sdhci_esdhc_probe()
1467 host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; in sdhci_esdhc_probe()
1469 if (esdhc->vendor_ver > VENDOR_V_22) in sdhci_esdhc_probe()
1470 host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; in sdhci_esdhc_probe()
1472 tp = of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"); in sdhci_esdhc_probe()
1475 host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; in sdhci_esdhc_probe()
1476 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; in sdhci_esdhc_probe()
1479 if (of_device_is_compatible(np, "fsl,p5040-esdhc") || in sdhci_esdhc_probe()
1480 of_device_is_compatible(np, "fsl,p5020-esdhc") || in sdhci_esdhc_probe()
1481 of_device_is_compatible(np, "fsl,p4080-esdhc") || in sdhci_esdhc_probe()
1482 of_device_is_compatible(np, "fsl,p1020-esdhc") || in sdhci_esdhc_probe()
1483 of_device_is_compatible(np, "fsl,t1040-esdhc")) in sdhci_esdhc_probe()
1484 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; in sdhci_esdhc_probe()
1486 if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) in sdhci_esdhc_probe()
1487 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; in sdhci_esdhc_probe()
1489 esdhc->quirk_ignore_data_inhibit = false; in sdhci_esdhc_probe()
1490 if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { in sdhci_esdhc_probe()
1492 * Freescale messed up with P2020 as it has a non-standard in sdhci_esdhc_probe()
1495 host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; in sdhci_esdhc_probe()
1496 esdhc->quirk_ignore_data_inhibit = true; in sdhci_esdhc_probe()
1500 ret = mmc_of_parse(host->mmc); in sdhci_esdhc_probe()
1504 mmc_of_parse_voltage(host->mmc, &host->ocr_mask); in sdhci_esdhc_probe()
1518 .name = "sdhci-esdhc",