Date: Thu, 22 Nov 2018 13:18:58 +0000 (UTC) From: Marius Strobl <marius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r340764 - stable/10/sys/dev/sdhci Message-ID: <201811221318.wAMDIwPp077383@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marius Date: Thu Nov 22 13:18:58 2018 New Revision: 340764 URL: https://svnweb.freebsd.org/changeset/base/340764 Log: MFC: r339007, r340543, r340654 - Add ACPI identifier for AMD eMMC 5.0 controller [1] - Add a quirk handling for AMDI0040 controllers allowing them to do HS400. [2] Submitted by: Rajesh Kumar [1], Shreyank Amartya (original version) [2] Modified: stable/10/sys/dev/sdhci/sdhci.c stable/10/sys/dev/sdhci/sdhci.h stable/10/sys/dev/sdhci/sdhci_acpi.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/sdhci/sdhci.c ============================================================================== --- stable/10/sys/dev/sdhci/sdhci.c Thu Nov 22 13:14:15 2018 (r340763) +++ stable/10/sys/dev/sdhci/sdhci.c Thu Nov 22 13:18:58 2018 (r340764) @@ -810,6 +810,9 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, if (slot->quirks & SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 && caps2 & SDHCI_CAN_MMC_HS400) host_caps |= MMC_CAP_MMC_HS400; + if (slot->quirks & SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 && + caps2 & SDHCI_CAN_SDR104) + host_caps |= MMC_CAP_MMC_HS400; /* * Disable UHS-I and eMMC modes if the set_uhs_timing method is the Modified: stable/10/sys/dev/sdhci/sdhci.h ============================================================================== --- stable/10/sys/dev/sdhci/sdhci.h Thu Nov 22 13:14:15 2018 (r340763) +++ stable/10/sys/dev/sdhci/sdhci.h Thu Nov 22 13:18:58 2018 (r340764) @@ -87,6 +87,8 @@ #define SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 (1 << 26) /* Controller support for SDHCI_CTRL2_PRESET_VALUE is broken. */ #define SDHCI_QUIRK_PRESET_VALUE_BROKEN (1 << 27) +/* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */ +#define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29) /* * Controller registers Modified: stable/10/sys/dev/sdhci/sdhci_acpi.c ============================================================================== --- stable/10/sys/dev/sdhci/sdhci_acpi.c Thu Nov 22 13:14:15 2018 (r340763) +++ stable/10/sys/dev/sdhci/sdhci_acpi.c Thu Nov 22 13:18:58 2018 (r340764) @@ -45,12 +45,15 @@ __FBSDID("$FreeBSD$"); #include <dev/acpica/acpivar.h> #include <dev/mmc/bridge.h> +#include <dev/mmc/mmcreg.h> #include <dev/sdhci/sdhci.h> #include "mmcbr_if.h" #include "sdhci_if.h" +#define SDHCI_AMD_RESET_DLL_REG 0x908 + static const struct sdhci_acpi_device { const char* hid; int uid; @@ -79,6 +82,9 @@ static const struct sdhci_acpi_device { SDHCI_QUIRK_MMC_DDR52 | SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | SDHCI_QUIRK_PRESET_VALUE_BROKEN }, + { "AMDI0040", 0, "AMD eMMC 5.0 Controller", + SDHCI_QUIRK_32BIT_DMA_SIZE | + SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 }, { NULL, 0, NULL, 0} }; @@ -87,16 +93,16 @@ static char *sdhci_ids[] = { "80860F16", "80865ACA", "80865ACC", + "AMDI0040", NULL }; struct sdhci_acpi_softc { - u_int quirks; /* Chip specific quirks */ - struct resource *irq_res; /* IRQ resource */ - void *intrhand; /* Interrupt handle */ - struct sdhci_slot slot; struct resource *mem_res; /* Memory resource */ + struct resource *irq_res; /* IRQ resource */ + void *intrhand; /* Interrupt handle */ + const struct sdhci_acpi_device *acpi_dev; }; static void sdhci_acpi_intr(void *arg); @@ -186,6 +192,52 @@ sdhci_acpi_write_multi_4(device_t dev, struct sdhci_sl bus_write_multi_stream_4(sc->mem_res, off, data, count); } +static void +sdhci_acpi_set_uhs_timing(device_t dev, struct sdhci_slot *slot) +{ + const struct sdhci_acpi_softc *sc; + const struct sdhci_acpi_device *acpi_dev; + const struct mmc_ios *ios; + device_t bus; + uint16_t old_timing; + enum mmc_bus_timing timing; + + bus = slot->bus; + old_timing = SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2); + old_timing &= SDHCI_CTRL2_UHS_MASK; + sdhci_generic_set_uhs_timing(dev, slot); + + sc = device_get_softc(dev); + acpi_dev = sc->acpi_dev; + /* + * AMDI0040 controllers require SDHCI_CTRL2_SAMPLING_CLOCK to be + * disabled when switching from HS200 to high speed and to always + * be turned on again when tuning for HS400. In the later case, + * an AMD-specific DLL reset additionally is needed. + */ + if (strcmp(acpi_dev->hid, "AMDI0040") == 0 && acpi_dev->uid == 0) { + ios = &slot->host.ios; + timing = ios->timing; + if (old_timing == SDHCI_CTRL2_UHS_SDR104 && + timing == bus_timing_hs) + SDHCI_WRITE_2(bus, slot, SDHCI_HOST_CONTROL2, + SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2) & + ~SDHCI_CTRL2_SAMPLING_CLOCK); + if (ios->clock > SD_SDR50_MAX && + old_timing != SDHCI_CTRL2_MMC_HS400 && + timing == bus_timing_mmc_hs400) { + SDHCI_WRITE_2(bus, slot, SDHCI_HOST_CONTROL2, + SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2) | + SDHCI_CTRL2_SAMPLING_CLOCK); + SDHCI_WRITE_4(bus, slot, SDHCI_AMD_RESET_DLL_REG, + 0x40003210); + DELAY(20); + SDHCI_WRITE_4(bus, slot, SDHCI_AMD_RESET_DLL_REG, + 0x40033210); + } + } +} + static const struct sdhci_acpi_device * sdhci_acpi_find_device(device_t dev) { @@ -234,13 +286,15 @@ sdhci_acpi_attach(device_t dev) { struct sdhci_acpi_softc *sc = device_get_softc(dev); int rid, err; + u_int quirks; const struct sdhci_acpi_device *acpi_dev; acpi_dev = sdhci_acpi_find_device(dev); if (acpi_dev == NULL) return (ENXIO); - sc->quirks = acpi_dev->quirks; + sc->acpi_dev = acpi_dev; + quirks = acpi_dev->quirks; /* Allocate IRQ. */ rid = 0; @@ -268,11 +322,10 @@ sdhci_acpi_attach(device_t dev) if (strcmp(acpi_dev->hid, "80860F14") == 0 && acpi_dev->uid == 1 && SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES) == 0x446cc8b2 && SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES2) == 0x00000807) - sc->quirks |= SDHCI_QUIRK_MMC_DDR52 | - SDHCI_QUIRK_DATA_TIMEOUT_1MHZ; - sc->quirks &= ~sdhci_quirk_clear; - sc->quirks |= sdhci_quirk_set; - sc->slot.quirks = sc->quirks; + quirks |= SDHCI_QUIRK_MMC_DDR52 | SDHCI_QUIRK_DATA_TIMEOUT_1MHZ; + quirks &= ~sdhci_quirk_clear; + quirks |= sdhci_quirk_set; + sc->slot.quirks = quirks; err = sdhci_init_slot(dev, &sc->slot, 0); if (err) { @@ -389,7 +442,7 @@ static device_method_t sdhci_methods[] = { DEVMETHOD(sdhci_write_2, sdhci_acpi_write_2), DEVMETHOD(sdhci_write_4, sdhci_acpi_write_4), DEVMETHOD(sdhci_write_multi_4, sdhci_acpi_write_multi_4), - DEVMETHOD(sdhci_set_uhs_timing, sdhci_generic_set_uhs_timing), + DEVMETHOD(sdhci_set_uhs_timing, sdhci_acpi_set_uhs_timing), DEVMETHOD_END };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811221318.wAMDIwPp077383>