reg = sdhci_readb(host, SDHCI_POWER_CONTROL);
reg |= 0x10;
sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); /* For eMMC, minimum is 1us but give it 9us for good measure */
udelay(9);
reg &= ~0x10;
sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); /* For eMMC, minimum is 200us but give it 300us for good measure */
usleep_range(300, 1000);
}
staticint amd_select_drive_strength(struct mmc_card *card, unsignedint max_dtr, int host_drv, int card_drv, int *host_driver_strength)
{ struct sdhci_host *host = mmc_priv(card->host);
u16 preset, preset_driver_strength;
/* * This method is only called by mmc_select_hs200 so we only need to * read from the HS200 (SDR104) preset register. * * Firmware that has "invalid/default" presets return a driver strength * of A. This matches the previously hard coded value.
*/
preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
preset_driver_strength = FIELD_GET(SDHCI_PRESET_DRV_MASK, preset);
/* * We want the controller driver strength to match the card's driver * strength so they have similar rise/fall times. * * The controller driver strength set by this method is sticky for all * timings after this method is called. This unfortunately means that * while HS400 tuning is in progress we end up with mismatched driver * strengths between the controller and the card. HS400 tuning requires * switching from HS400->DDR52->HS->HS200->HS400. So the driver mismatch * happens while in DDR52 and HS modes. This has not been observed to * cause problems. Enabling presets would fix this issue.
*/
*host_driver_strength = preset_driver_strength;
/* * The resulting card driver strength is only set when switching the * card's timing to HS200 or HS400. The card will use the default driver * strength (B) for any other mode.
*/ return preset_driver_strength;
}
/* * The initialization sequence for HS400 is: * HS->HS200->Perform Tuning->HS->HS400 * * The re-tuning sequence is: * HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400 * * The AMD eMMC Controller can only use the tuned clock while in HS200 and HS400 * mode. If we switch to a different mode, we need to disable the tuned clock. * If we have previously performed tuning and switch back to HS200 or * HS400, we can re-enable the tuned clock. *
*/ staticvoid amd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{ struct sdhci_host *host = mmc_priv(mmc); struct sdhci_acpi_host *acpi_host = sdhci_priv(host); struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host); unsignedint old_timing = host->timing;
u16 val;
sdhci_set_ios(mmc, ios);
if (old_timing != host->timing && amd_host->tuned_clock) { if (host->timing == MMC_TIMING_MMC_HS400 ||
host->timing == MMC_TIMING_MMC_HS200) {
val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
val |= SDHCI_CTRL_TUNED_CLK;
sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
} else {
val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
val &= ~SDHCI_CTRL_TUNED_CLK;
sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
}
/* DLL is only required for HS400 */ if (host->timing == MMC_TIMING_MMC_HS400 &&
!amd_host->dll_enabled)
sdhci_acpi_amd_hs400_dll(host, true);
}
}
/* * There are two types of presets out in the wild: * 1) Default/broken presets. * These presets have two sets of problems: * a) The clock divisor for SDR12, SDR25, and SDR50 is too small. * This results in clock frequencies that are 2x higher than * acceptable. i.e., SDR12 = 25 MHz, SDR25 = 50 MHz, SDR50 = * 100 MHz.x * b) The HS200 and HS400 driver strengths don't match. * By default, the SDR104 preset register has a driver strength of * A, but the (internal) HS400 preset register has a driver * strength of B. As part of initializing HS400, HS200 tuning * needs to be performed. Having different driver strengths * between tuning and operation is wrong. It results in different * rise/fall times that lead to incorrect sampling. * 2) Firmware with properly initialized presets. * These presets have proper clock divisors. i.e., SDR12 => 12MHz, * SDR25 => 25 MHz, SDR50 => 50 MHz. Additionally the HS200 and * HS400 preset driver strengths match. * * Enabling presets for HS400 doesn't work for the following reasons: * 1) sdhci_set_ios has a hard coded list of timings that are used * to determine if presets should be enabled. * 2) sdhci_get_preset_value is using a non-standard register to * read out HS400 presets. The AMD controller doesn't support this * non-standard register. In fact, it doesn't expose the HS400 * preset register anywhere in the SDHCI memory map. This results * in reading a garbage value and using the wrong presets. * * Since HS400 and HS200 presets must be identical, we could * instead use the SDR104 preset register. * * If the above issues are resolved we could remove this quirk for * firmware that has valid presets (i.e., SDR12 <= 12 MHz).
*/
host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
/* Please keep this list sorted alphabetically */ staticconststruct dmi_system_id sdhci_acpi_quirks[] = {
{ /* * The Acer Aspire Switch 10 (SW5-012) microSD slot always * reports the card being write-protected even though microSD * cards do not have a write-protect switch at all.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
},
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
},
{ /* Asus T100TA, needs pull-up for cd but DSDT GpioInt has NoPull set */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
},
.driver_data = (void *)DMI_QUIRK_SD_CD_ENABLE_PULL_UP,
},
{ /* * The Lenovo Miix 320-10ICR has a bug in the _PS0 method of * the SHC1 ACPI device, this bug causes it to reprogram the * wrong LDO (DLDO3) to 1.8V if 1.8V modes are used and the * card is (runtime) suspended + resumed. DLDO3 is used for * the LCD and setting it to 1.8V causes the LCD to go black.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
},
.driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
},
{ /* * Lenovo Yoga Tablet 2 Pro 1380F/L (13" Android version) this * has broken WP reporting and an inverted CD signal. * Note this has more or less the same BIOS as the Lenovo Yoga * Tablet 2 830F/L or 1050F/L (8" and 10" Android), but unlike * the 830 / 1050 models which share the same mainboard this * model has a different mainboard and the inverted CD and * broken WP are unique to this board.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"), /* Full match so as to NOT match the 830/1050 BIOS */
DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21.X64.0005.R00.1504101516"),
},
.driver_data = (void *)(DMI_QUIRK_SD_NO_WRITE_PROTECT |
DMI_QUIRK_SD_CD_ACTIVE_HIGH),
},
{ /* * The Toshiba WT8-B's microSD slot always reports the card being * write-protected.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA ENCORE 2 WT8-B"),
},
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
},
{ /* * The Toshiba WT10-A's microSD slot always reports the card being * write-protected.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A"),
},
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
},
{} /* Terminating entry */
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.