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"
65 { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk},
66 { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk},
67 { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk},
68 { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk},
69 { .compatible = "fsl,mpc8379-esdhc" },
70 { .compatible = "fsl,mpc8536-esdhc" },
94 * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register
124 if (esdhc->vendor_ver > VENDOR_V_22) { in esdhc_readl_fixup()
149 if (esdhc->quirk_ignore_data_inhibit) in esdhc_readl_fixup()
178 return pltfm_host->xfer_mode_shadow; in esdhc_readw_fixup()
184 /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect in esdhc_readw_fixup()
188 (esdhc->quirk_incorrect_hostver)) in esdhc_readw_fixup()
217 * esdhc_write*_fixup - Fixup the SD spec register value so that it could be
263 pltfm_host->xfer_mode_shadow = value; in esdhc_writew_fixup()
266 ret = (value << 16) | pltfm_host->xfer_mode_shadow; in esdhc_writew_fixup()
276 * non-standard blksz of 4096 bytes that we don't support in esdhc_writew_fixup()
307 if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) in esdhc_writeb_fixup()
332 value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); in esdhc_be_readl()
334 value = ioread32be(host->ioaddr + reg); in esdhc_be_readl()
347 value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); in esdhc_le_readl()
349 value = ioread32(host->ioaddr + reg); in esdhc_le_readl()
362 value = ioread32be(host->ioaddr + base); in esdhc_be_readw()
373 value = ioread32(host->ioaddr + base); in esdhc_le_readw()
384 value = ioread32be(host->ioaddr + base); in esdhc_be_readb()
395 value = ioread32(host->ioaddr + base); in esdhc_le_readb()
405 iowrite32be(value, host->ioaddr + reg); in esdhc_be_writel()
413 iowrite32(value, host->ioaddr + reg); in esdhc_le_writel()
424 value = ioread32be(host->ioaddr + base); in esdhc_be_writew()
427 iowrite32be(ret, host->ioaddr + base); in esdhc_be_writew()
429 /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set in esdhc_be_writew()
434 esdhc->in_sw_tuning) { in esdhc_be_writew()
437 iowrite32be(ret, host->ioaddr + base); in esdhc_be_writew()
450 value = ioread32(host->ioaddr + base); in esdhc_le_writew()
453 iowrite32(ret, host->ioaddr + base); in esdhc_le_writew()
455 /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set in esdhc_le_writew()
460 esdhc->in_sw_tuning) { in esdhc_le_writew()
463 iowrite32(ret, host->ioaddr + base); in esdhc_le_writew()
474 value = ioread32be(host->ioaddr + base); in esdhc_be_writeb()
476 iowrite32be(ret, host->ioaddr + base); in esdhc_be_writeb()
485 value = ioread32(host->ioaddr + base); in esdhc_le_writeb()
487 iowrite32(ret, host->ioaddr + base); in esdhc_le_writeb()
495 * and re-issue the entire read transaction from beginning.
507 (esdhc->vendor_ver == VENDOR_V_23); in esdhc_of_adma_workaround()
511 host->data->error = 0; in esdhc_of_adma_workaround()
512 dmastart = sg_dma_address(host->data->sg); in esdhc_of_adma_workaround()
513 dmanow = dmastart + host->data->bytes_xfered; in esdhc_of_adma_workaround()
517 dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + in esdhc_of_adma_workaround()
519 host->data->bytes_xfered = dmanow - dmastart; in esdhc_of_adma_workaround()
527 struct device *dev = mmc_dev(host->mmc); in esdhc_of_enable_dma()
529 if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || in esdhc_of_enable_dma()
530 of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) { in esdhc_of_enable_dma()
538 if (of_dma_is_coherent(dev->of_node)) in esdhc_of_enable_dma()
552 if (esdhc->peripheral_clock) in esdhc_of_get_max_clock()
553 return esdhc->peripheral_clock; in esdhc_of_get_max_clock()
555 return pltfm_host->clock; in esdhc_of_get_max_clock()
564 if (esdhc->peripheral_clock) in esdhc_of_get_min_clock()
565 clock = esdhc->peripheral_clock; in esdhc_of_get_min_clock()
567 clock = pltfm_host->clock; in esdhc_of_get_min_clock()
584 if (esdhc->vendor_ver <= VENDOR_V_22) in esdhc_clock_enable()
602 while (esdhc->vendor_ver > VENDOR_V_22) { in esdhc_clock_enable()
609 mmc_hostname(host->mmc)); in esdhc_clock_enable()
635 mmc_hostname(host->mmc)); in esdhc_flush_async_fifo()
652 host->mmc->actual_clock = 0; in esdhc_of_set_clock()
658 if (esdhc->vendor_ver < VENDOR_V_23) in esdhc_of_set_clock()
662 if (host->mmc->card && mmc_card_sd(host->mmc->card) && in esdhc_of_set_clock()
663 esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) in esdhc_of_set_clock()
664 clock_fixup = esdhc->clk_fixup->sd_dflt_max_clk; in esdhc_of_set_clock()
665 else if (esdhc->clk_fixup) in esdhc_of_set_clock()
666 clock_fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; in esdhc_of_set_clock()
672 while (host->max_clk / pre_div / 16 > clock_fixup && pre_div < 256) in esdhc_of_set_clock()
675 while (host->max_clk / pre_div / div > clock_fixup && div < 16) in esdhc_of_set_clock()
678 esdhc->div_ratio = pre_div * div; in esdhc_of_set_clock()
681 if (esdhc->quirk_limited_clk_division && in esdhc_of_set_clock()
683 (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || in esdhc_of_set_clock()
684 host->flags & SDHCI_HS400_TUNING)) { in esdhc_of_set_clock()
685 if (esdhc->div_ratio <= 4) { in esdhc_of_set_clock()
688 } else if (esdhc->div_ratio <= 8) { in esdhc_of_set_clock()
691 } else if (esdhc->div_ratio <= 12) { in esdhc_of_set_clock()
696 mmc_hostname(host->mmc)); in esdhc_of_set_clock()
698 esdhc->div_ratio = pre_div * div; in esdhc_of_set_clock()
701 host->mmc->actual_clock = host->max_clk / esdhc->div_ratio; in esdhc_of_set_clock()
703 dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", in esdhc_of_set_clock()
704 clock, host->mmc->actual_clock); in esdhc_of_set_clock()
708 div--; in esdhc_of_set_clock()
723 while (esdhc->vendor_ver > VENDOR_V_22) { in esdhc_of_set_clock()
730 mmc_hostname(host->mmc)); in esdhc_of_set_clock()
737 if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && in esdhc_of_set_clock()
747 if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) in esdhc_of_set_clock()
763 mmc_hostname(host->mmc)); in esdhc_of_set_clock()
806 if (esdhc->quirk_delay_before_data_reset && in esdhc_reset()
808 (host->flags & SDHCI_REQ_USE_DMA)) in esdhc_reset()
812 * Save bus-width for eSDHC whose vendor version is 2.2 in esdhc_reset()
816 (esdhc->vendor_ver <= VENDOR_V_22)) { in esdhc_reset()
824 * Restore bus-width setting and interrupt registers for eSDHC in esdhc_reset()
828 (esdhc->vendor_ver <= VENDOR_V_22)) { in esdhc_reset()
834 sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); in esdhc_reset()
835 sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); in esdhc_reset()
843 (esdhc->spec_ver >= SDHCI_SPEC_300)) { in esdhc_reset()
852 if (esdhc->quirk_unreliable_pulse_detection) { in esdhc_reset()
866 { .compatible = "fsl,t1040-scfg", },
867 { .compatible = "fsl,ls1012a-scfg", },
868 { .compatible = "fsl,ls1046a-scfg", },
891 if (host->version < SDHCI_SPEC_300) in esdhc_signal_voltage_switch()
896 switch (ios->signal_voltage) { in esdhc_signal_voltage_switch()
1000 if (esdhc->quirk_tuning_erratum_type1) { in esdhc_prepare_sw_tuning()
1001 *window_start = 5 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1002 *window_end = 3 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1013 /* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 in esdhc_prepare_sw_tuning()
1014 * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2, in esdhc_prepare_sw_tuning()
1019 if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) { in esdhc_prepare_sw_tuning()
1020 *window_start = 8 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1021 *window_end = 4 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1023 *window_start = 5 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1024 *window_end = 3 * esdhc->div_ratio; in esdhc_prepare_sw_tuning()
1043 /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ in esdhc_execute_sw_tuning()
1049 esdhc->in_sw_tuning = true; in esdhc_execute_sw_tuning()
1051 esdhc->in_sw_tuning = false; in esdhc_execute_sw_tuning()
1066 /* For tuning mode, the sd clock divisor value in esdhc_execute_tuning()
1069 clk = esdhc->peripheral_clock / 3; in esdhc_execute_tuning()
1070 if (host->clock > clk) in esdhc_execute_tuning()
1077 * during tuning. If the SD card is too slow sending the response, the in esdhc_execute_tuning()
1079 * is triggered. This leads to tuning errors. in esdhc_execute_tuning()
1086 hs400_tuning = host->flags & SDHCI_HS400_TUNING; in esdhc_execute_tuning()
1089 if (esdhc->quirk_limited_clk_division && in esdhc_execute_tuning()
1091 esdhc_of_set_clock(host, host->clock); in esdhc_execute_tuning()
1093 /* Do HW tuning */ in esdhc_execute_tuning()
1103 /* For type2 affected platforms of the tuning erratum, in esdhc_execute_tuning()
1104 * tuning may succeed although eSDHC might not have in esdhc_execute_tuning()
1105 * tuned properly. Need to check tuning window. in esdhc_execute_tuning()
1107 if (esdhc->quirk_tuning_erratum_type2 && in esdhc_execute_tuning()
1108 !host->tuning_err) { in esdhc_execute_tuning()
1111 if (abs(window_start - window_end) > in esdhc_execute_tuning()
1112 (4 * esdhc->div_ratio + 2)) in esdhc_execute_tuning()
1113 host->tuning_err = -EAGAIN; in esdhc_execute_tuning()
1116 /* If HW tuning fails and triggers erratum, in esdhc_execute_tuning()
1119 ret = host->tuning_err; in esdhc_execute_tuning()
1120 if (ret == -EAGAIN && in esdhc_execute_tuning()
1121 (esdhc->quirk_tuning_erratum_type1 || in esdhc_execute_tuning()
1122 esdhc->quirk_tuning_erratum_type2)) { in esdhc_execute_tuning()
1123 /* Recover HS400 tuning flag */ in esdhc_execute_tuning()
1125 host->flags |= SDHCI_HS400_TUNING; in esdhc_execute_tuning()
1126 pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", in esdhc_execute_tuning()
1128 /* Do SW tuning */ in esdhc_execute_tuning()
1137 /* Retry both HW/SW tuning with reduced clock. */ in esdhc_execute_tuning()
1138 ret = host->tuning_err; in esdhc_execute_tuning()
1139 if (ret == -EAGAIN && retries) { in esdhc_execute_tuning()
1140 /* Recover HS400 tuning flag */ in esdhc_execute_tuning()
1142 host->flags |= SDHCI_HS400_TUNING; in esdhc_execute_tuning()
1144 clk = host->max_clk / (esdhc->div_ratio + 1); in esdhc_execute_tuning()
1146 pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", in esdhc_execute_tuning()
1154 } while (retries--); in esdhc_execute_tuning()
1175 * exit HS400 mode before re-setting any speed mode. in esdhc_set_uhs_signaling()
1216 if (esdhc->quirk_trans_complete_erratum) { in esdhc_irq()
1238 if (host->tuning_mode != SDHCI_TUNING_MODE_3) in esdhc_of_suspend()
1239 mmc_retune_needed(host->mmc); in esdhc_of_suspend()
1250 /* Isn't this already done by sdhci_resume_host() ? --rmk */ in esdhc_of_resume()
1349 esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> in esdhc_init()
1351 esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; in esdhc_init()
1353 esdhc->quirk_incorrect_hostver = true; in esdhc_init()
1355 esdhc->quirk_incorrect_hostver = false; in esdhc_init()
1358 esdhc->quirk_limited_clk_division = true; in esdhc_init()
1360 esdhc->quirk_limited_clk_division = false; in esdhc_init()
1363 esdhc->quirk_unreliable_pulse_detection = true; in esdhc_init()
1365 esdhc->quirk_unreliable_pulse_detection = false; in esdhc_init()
1367 match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); in esdhc_init()
1369 esdhc->clk_fixup = match->data; in esdhc_init()
1370 np = pdev->dev.of_node; in esdhc_init()
1372 if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { in esdhc_init()
1373 esdhc->quirk_delay_before_data_reset = true; in esdhc_init()
1374 esdhc->quirk_trans_complete_erratum = true; in esdhc_init()
1380 * esdhc->peripheral_clock would be assigned with a value in esdhc_init()
1386 if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || in esdhc_init()
1387 of_device_is_compatible(np, "fsl,ls1028a-esdhc") || in esdhc_init()
1388 of_device_is_compatible(np, "fsl,ls1088a-esdhc")) in esdhc_init()
1389 esdhc->peripheral_clock = clk_get_rate(clk) / 2; in esdhc_init()
1391 esdhc->peripheral_clock = clk_get_rate(clk); in esdhc_init()
1403 if (esdhc->peripheral_clock) in esdhc_init()
1425 np = pdev->dev.of_node; in sdhci_esdhc_probe()
1427 if (of_property_read_bool(np, "little-endian")) in sdhci_esdhc_probe()
1437 host->mmc_host_ops.start_signal_voltage_switch = in sdhci_esdhc_probe()
1439 host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; in sdhci_esdhc_probe()
1440 host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; in sdhci_esdhc_probe()
1441 host->tuning_delay = 1; in sdhci_esdhc_probe()
1450 esdhc->quirk_tuning_erratum_type1 = true; in sdhci_esdhc_probe()
1452 esdhc->quirk_tuning_erratum_type1 = false; in sdhci_esdhc_probe()
1455 esdhc->quirk_tuning_erratum_type2 = true; in sdhci_esdhc_probe()
1457 esdhc->quirk_tuning_erratum_type2 = false; in sdhci_esdhc_probe()
1459 if (esdhc->vendor_ver == VENDOR_V_22) in sdhci_esdhc_probe()
1460 host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; in sdhci_esdhc_probe()
1462 if (esdhc->vendor_ver > VENDOR_V_22) in sdhci_esdhc_probe()
1463 host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; in sdhci_esdhc_probe()
1465 if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { in sdhci_esdhc_probe()
1466 host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; in sdhci_esdhc_probe()
1467 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; in sdhci_esdhc_probe()
1470 if (of_device_is_compatible(np, "fsl,p5040-esdhc") || in sdhci_esdhc_probe()
1471 of_device_is_compatible(np, "fsl,p5020-esdhc") || in sdhci_esdhc_probe()
1472 of_device_is_compatible(np, "fsl,p4080-esdhc") || in sdhci_esdhc_probe()
1473 of_device_is_compatible(np, "fsl,p1020-esdhc") || in sdhci_esdhc_probe()
1474 of_device_is_compatible(np, "fsl,t1040-esdhc")) in sdhci_esdhc_probe()
1475 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; in sdhci_esdhc_probe()
1477 if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) in sdhci_esdhc_probe()
1478 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; in sdhci_esdhc_probe()
1480 esdhc->quirk_ignore_data_inhibit = false; in sdhci_esdhc_probe()
1481 if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { in sdhci_esdhc_probe()
1483 * Freescale messed up with P2020 as it has a non-standard in sdhci_esdhc_probe()
1486 host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; in sdhci_esdhc_probe()
1487 esdhc->quirk_ignore_data_inhibit = true; in sdhci_esdhc_probe()
1491 ret = mmc_of_parse(host->mmc); in sdhci_esdhc_probe()
1495 mmc_of_parse_voltage(np, &host->ocr_mask); in sdhci_esdhc_probe()
1509 .name = "sdhci-esdhc",