Created
June 23, 2016 23:33
-
-
Save nonakap/a668e1e5b01a217a29e3f0c91dc26a6a to your computer and use it in GitHub Desktop.
sdhc(4): Add hardware reset support for Intel eMMC controller.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/sys/dev/acpi/sdhc_acpi.c b/sys/dev/acpi/sdhc_acpi.c | |
| index 8b1b741..e91bfd0 100644 | |
| --- a/sys/dev/acpi/sdhc_acpi.c | |
| +++ b/sys/dev/acpi/sdhc_acpi.c | |
| @@ -50,6 +50,9 @@ static bool sdhc_acpi_resume(device_t, const pmf_qual_t *); | |
| struct sdhc_acpi_softc { | |
| struct sdhc_softc sc; | |
| + bus_space_tag_t sc_memt; | |
| + bus_space_handle_t sc_memh; | |
| + bus_size_t sc_memsize; | |
| int sc_irq; | |
| ACPI_HANDLE sc_crs, sc_srs; | |
| @@ -59,14 +62,58 @@ struct sdhc_acpi_softc { | |
| CFATTACH_DECL_NEW(sdhc_acpi, sizeof(struct sdhc_acpi_softc), | |
| sdhc_acpi_match, sdhc_acpi_attach, sdhc_acpi_detach, NULL); | |
| -static uint32_t sdhc_acpi_intr(void *); | |
| - | |
| -static const char * const sdhc_acpi_ids[] = { | |
| - "80860F14", | |
| - "80860F16", | |
| - NULL | |
| +static uint32_t sdhc_acpi_intr(void *); | |
| +static void sdhc_acpi_intel_emmc_hw_reset(struct sdhc_softc *, | |
| + struct sdhc_host *); | |
| + | |
| +static const struct sdhc_acpi_slot { | |
| + const char *hid; | |
| + const char *uid; | |
| + int type; | |
| +#define SLOT_TYPE_SD 0 /* SD or SDIO */ | |
| +#define SLOT_TYPE_EMMC 1 /* eMMC */ | |
| +} sdhc_acpi_slot_map[] = { | |
| + { "80865ACA", NULL, SLOT_TYPE_SD }, | |
| + { "80865ACC", NULL, SLOT_TYPE_EMMC }, | |
| + { "80865AD0", NULL, SLOT_TYPE_SD }, | |
| + { "80860F14", "1", SLOT_TYPE_EMMC }, | |
| + { "80860F14", "3", SLOT_TYPE_SD }, | |
| + { "80860F16", NULL, SLOT_TYPE_SD }, | |
| + { "INT33BB", "2", SLOT_TYPE_SD }, | |
| + { "INT33BB", "3", SLOT_TYPE_SD }, | |
| + { "INT33C6", NULL, SLOT_TYPE_SD }, | |
| + { "INT3436", NULL, SLOT_TYPE_SD }, | |
| + { "INT344D", NULL, SLOT_TYPE_SD }, | |
| + { "PNP0D40", NULL, SLOT_TYPE_SD }, | |
| + { "PNP0FFF", "3", SLOT_TYPE_SD }, | |
| }; | |
| +static const struct sdhc_acpi_slot * | |
| +sdhc_acpi_find_slot(ACPI_DEVICE_INFO *ad) | |
| +{ | |
| + const struct sdhc_acpi_slot *slot; | |
| + const char *hid, *uid; | |
| + size_t i; | |
| + | |
| + hid = ad->HardwareId.String; | |
| + uid = ad->UniqueId.String; | |
| + | |
| + if (!(ad->Valid & ACPI_VALID_HID) || hid == NULL) | |
| + return NULL; | |
| + | |
| + for (i = 0; i < __arraycount(sdhc_acpi_slot_map); i++) { | |
| + slot = &sdhc_acpi_slot_map[i]; | |
| + if (strcmp(hid, slot->hid) == 0) { | |
| + if (slot->uid == NULL || | |
| + ((ad->Valid & ACPI_VALID_UID) != 0 && | |
| + uid != NULL && | |
| + strcmp(uid, slot->uid) == 0)) | |
| + return slot; | |
| + } | |
| + } | |
| + return NULL; | |
| +} | |
| + | |
| static int | |
| sdhc_acpi_match(device_t parent, cfdata_t match, void *opaque) | |
| { | |
| @@ -75,7 +122,7 @@ sdhc_acpi_match(device_t parent, cfdata_t match, void *opaque) | |
| if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | |
| return 0; | |
| - return acpi_match_hid(aa->aa_node->ad_devinfo, sdhc_acpi_ids); | |
| + return sdhc_acpi_find_slot(aa->aa_node->ad_devinfo) != NULL; | |
| } | |
| static void | |
| @@ -83,17 +130,22 @@ sdhc_acpi_attach(device_t parent, device_t self, void *opaque) | |
| { | |
| struct sdhc_acpi_softc *sc = device_private(self); | |
| struct acpi_attach_args *aa = opaque; | |
| + const struct sdhc_acpi_slot *slot; | |
| struct acpi_resources res; | |
| struct acpi_mem *mem; | |
| struct acpi_irq *irq; | |
| - bus_space_handle_t memh; | |
| ACPI_STATUS rv; | |
| sc->sc.sc_dev = self; | |
| sc->sc.sc_dmat = aa->aa_dmat; | |
| sc->sc.sc_host = NULL; | |
| + sc->sc_memt = aa->aa_memt; | |
| sc->sc_irq = -1; | |
| + slot = sdhc_acpi_find_slot(aa->aa_node->ad_devinfo); | |
| + if (slot->type == SLOT_TYPE_EMMC) | |
| + sc->sc.sc_vendor_hw_reset = sdhc_acpi_intel_emmc_hw_reset; | |
| + | |
| rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", | |
| &res, &acpi_resource_parse_ops_default); | |
| if (ACPI_FAILURE(rv)) | |
| @@ -116,9 +168,10 @@ sdhc_acpi_attach(device_t parent, device_t self, void *opaque) | |
| aprint_error_dev(self, "incomplete resources\n"); | |
| goto cleanup; | |
| } | |
| + sc->sc_memsize = mem->ar_length; | |
| - if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, | |
| - &memh)) { | |
| + if (bus_space_map(sc->sc_memt, mem->ar_base, sc->sc_memsize, 0, | |
| + &sc->sc_memh)) { | |
| aprint_error_dev(self, "couldn't map registers\n"); | |
| goto cleanup; | |
| } | |
| @@ -128,19 +181,20 @@ sdhc_acpi_attach(device_t parent, device_t self, void *opaque) | |
| if (ACPI_FAILURE(rv)) { | |
| aprint_error_dev(self, | |
| "couldn't establish interrupt handler\n"); | |
| - goto cleanup; | |
| + goto unmap; | |
| } | |
| sc->sc_irq = irq->ar_irq; | |
| sc->sc.sc_host = kmem_zalloc(sizeof(struct sdhc_host *), KM_NOSLEEP); | |
| if (sc->sc.sc_host == NULL) { | |
| aprint_error_dev(self, "couldn't alloc memory\n"); | |
| - goto cleanup; | |
| + goto intr_disestablish; | |
| } | |
| - if (sdhc_host_found(&sc->sc, aa->aa_memt, memh, mem->ar_length) != 0) { | |
| + if (sdhc_host_found(&sc->sc, sc->sc_memt, sc->sc_memh, | |
| + sc->sc_memsize) != 0) { | |
| aprint_error_dev(self, "couldn't initialize host\n"); | |
| - goto cleanup; | |
| + goto fail; | |
| } | |
| if (!pmf_device_register1(self, sdhc_suspend, sdhc_acpi_resume, | |
| @@ -151,15 +205,23 @@ sdhc_acpi_attach(device_t parent, device_t self, void *opaque) | |
| acpi_resource_cleanup(&res); | |
| return; | |
| -cleanup: | |
| - acpi_resource_cleanup(&res); | |
| - if (sc->sc_crs_buffer.Pointer) | |
| - ACPI_FREE(sc->sc_crs_buffer.Pointer); | |
| +fail: | |
| + if (sc->sc.sc_host != NULL) | |
| + kmem_free(sc->sc.sc_host, sizeof(struct sdhc_host *)); | |
| + sc->sc.sc_host = NULL; | |
| +intr_disestablish: | |
| if (sc->sc_irq >= 0) | |
| /* XXX acpi_intr_disestablish? */ | |
| AcpiOsRemoveInterruptHandler(sc->sc_irq, sdhc_acpi_intr); | |
| - if (sc->sc.sc_host != NULL) | |
| - kmem_free(sc->sc.sc_host, sizeof(struct sdhc_host *)); | |
| + sc->sc_irq = -1; | |
| +unmap: | |
| + bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize); | |
| + sc->sc_memsize = 0; | |
| +cleanup: | |
| + if (sc->sc_crs_buffer.Pointer) | |
| + ACPI_FREE(sc->sc_crs_buffer.Pointer); | |
| + sc->sc_crs_buffer.Pointer = NULL; | |
| + acpi_resource_cleanup(&res); | |
| } | |
| static int | |
| @@ -170,9 +232,6 @@ sdhc_acpi_detach(device_t self, int flags) | |
| pmf_device_deregister(self); | |
| - if (sc->sc_crs_buffer.Pointer) | |
| - ACPI_FREE(sc->sc_crs_buffer.Pointer); | |
| - | |
| rv = sdhc_detach(&sc->sc, flags); | |
| if (rv) | |
| return rv; | |
| @@ -184,6 +243,12 @@ sdhc_acpi_detach(device_t self, int flags) | |
| if (sc->sc.sc_host != NULL) | |
| kmem_free(sc->sc.sc_host, sizeof(struct sdhc_host *)); | |
| + if (sc->sc_memsize > 0) | |
| + bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize); | |
| + | |
| + if (sc->sc_crs_buffer.Pointer) | |
| + ACPI_FREE(sc->sc_crs_buffer.Pointer); | |
| + | |
| return 0; | |
| } | |
| @@ -212,3 +277,25 @@ sdhc_acpi_intr(void *context) | |
| return ACPI_INTERRUPT_NOT_HANDLED; | |
| return ACPI_INTERRUPT_HANDLED; | |
| } | |
| + | |
| +static void | |
| +sdhc_acpi_intel_emmc_hw_reset(struct sdhc_softc *sc, struct sdhc_host *hp) | |
| +{ | |
| + kmutex_t *plock = sdhc_host_lock(hp); | |
| + uint8_t reg; | |
| + | |
| + mutex_enter(plock); | |
| + | |
| + reg = sdhc_host_read_1(hp, SDHC_POWER_CTL); | |
| + reg |= 0x10; | |
| + sdhc_host_write_1(hp, SDHC_POWER_CTL, reg); | |
| + | |
| + sdmmc_delay(10); | |
| + | |
| + reg &= ~0x10; | |
| + sdhc_host_write_1(hp, SDHC_POWER_CTL, reg); | |
| + | |
| + sdmmc_delay(1000); | |
| + | |
| + mutex_exit(plock); | |
| +} | |
| diff --git a/sys/dev/pci/sdhc_pci.c b/sys/dev/pci/sdhc_pci.c | |
| index a7b09cd..e18ec5e 100644 | |
| --- a/sys/dev/pci/sdhc_pci.c | |
| +++ b/sys/dev/pci/sdhc_pci.c | |
| @@ -81,11 +81,12 @@ static const struct sdhc_pci_quirk { | |
| u_int function; | |
| uint32_t flags; | |
| -#define SDHC_PCI_QUIRK_FORCE_DMA (1U << 0) | |
| -#define SDHC_PCI_QUIRK_TI_HACK (1U << 1) | |
| -#define SDHC_PCI_QUIRK_NO_PWR0 (1U << 2) | |
| -#define SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK (1U << 3) | |
| -#define SDHC_PCI_QUIRK_RICOH_SLOW_SDR50_HACK (1U << 4) | |
| +#define SDHC_PCI_QUIRK_FORCE_DMA __BIT(0) | |
| +#define SDHC_PCI_QUIRK_TI_HACK __BIT(1) | |
| +#define SDHC_PCI_QUIRK_NO_PWR0 __BIT(2) | |
| +#define SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK __BIT(3) | |
| +#define SDHC_PCI_QUIRK_RICOH_SLOW_SDR50_HACK __BIT(4) | |
| +#define SDHC_PCI_QUIRK_INTEL_EMMC_HW_RESET __BIT(5) | |
| } sdhc_pci_quirk_table[] = { | |
| { | |
| PCI_VENDOR_TI, | |
| @@ -138,10 +139,39 @@ static const struct sdhc_pci_quirk { | |
| ~0, | |
| SDHC_PCI_QUIRK_FORCE_DMA | |
| }, | |
| + | |
| + { | |
| + PCI_VENDOR_INTEL, | |
| + PCI_PRODUCT_INTEL_BAYTRAIL_SCC_MMC, | |
| + 0xffff, | |
| + 0xffff, | |
| + ~0, | |
| + SDHC_PCI_QUIRK_INTEL_EMMC_HW_RESET | |
| + }, | |
| + | |
| + { | |
| + PCI_VENDOR_INTEL, | |
| + PCI_PRODUCT_INTEL_BSW_SSC_MMC, | |
| + 0xffff, | |
| + 0xffff, | |
| + ~0, | |
| + SDHC_PCI_QUIRK_INTEL_EMMC_HW_RESET | |
| + }, | |
| + | |
| + { | |
| + PCI_VENDOR_INTEL, | |
| + PCI_PRODUCT_INTEL_100SERIES_LP_EMMC, | |
| + 0xffff, | |
| + 0xffff, | |
| + ~0, | |
| + SDHC_PCI_QUIRK_INTEL_EMMC_HW_RESET | |
| + }, | |
| }; | |
| static void sdhc_pci_quirk_ti_hack(struct pci_attach_args *); | |
| static void sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *); | |
| +static void sdhc_pci_intel_emmc_hw_reset(struct sdhc_softc *, | |
| + struct sdhc_host *); | |
| static uint32_t | |
| sdhc_pci_lookup_quirk_flags(struct pci_attach_args *pa) | |
| @@ -242,6 +272,8 @@ sdhc_pci_attach(device_t parent, device_t self, void *aux) | |
| sdhc_pci_quirk_ricoh_lower_freq_hack(pa); | |
| if (ISSET(flags, SDHC_PCI_QUIRK_RICOH_SLOW_SDR50_HACK)) | |
| SET(sc->sc.sc_flags, SDHC_FLAG_SLOW_SDR50); | |
| + if (ISSET(flags, SDHC_PCI_QUIRK_INTEL_EMMC_HW_RESET)) | |
| + sc->sc.sc_vendor_hw_reset = sdhc_pci_intel_emmc_hw_reset; | |
| /* | |
| * Map and attach all hosts supported by the host controller. | |
| @@ -410,3 +442,25 @@ sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *pa) | |
| sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x00); | |
| printf("quirked\n"); | |
| } | |
| + | |
| +static void | |
| +sdhc_pci_intel_emmc_hw_reset(struct sdhc_softc *sc, struct sdhc_host *hp) | |
| +{ | |
| + kmutex_t *plock = sdhc_host_lock(hp); | |
| + uint8_t reg; | |
| + | |
| + mutex_enter(plock); | |
| + | |
| + reg = sdhc_host_read_1(hp, SDHC_POWER_CTL); | |
| + reg |= 0x10; | |
| + sdhc_host_write_1(hp, SDHC_POWER_CTL, reg); | |
| + | |
| + sdmmc_delay(10); | |
| + | |
| + reg &= ~0x10; | |
| + sdhc_host_write_1(hp, SDHC_POWER_CTL, reg); | |
| + | |
| + sdmmc_delay(1000); | |
| + | |
| + mutex_exit(plock); | |
| +} | |
| diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c | |
| index 18c60f6..2ae9af2 100644 | |
| --- a/sys/dev/sdmmc/sdhc.c | |
| +++ b/sys/dev/sdmmc/sdhc.c | |
| @@ -192,6 +192,7 @@ static int sdhc_signal_voltage(sdmmc_chipset_handle_t, int); | |
| static int sdhc_execute_tuning1(struct sdhc_host *, int); | |
| static int sdhc_execute_tuning(sdmmc_chipset_handle_t, int); | |
| static void sdhc_tuning_timer(void *); | |
| +static void sdhc_hw_reset(sdmmc_chipset_handle_t); | |
| static int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *); | |
| static int sdhc_wait_state(struct sdhc_host *, uint32_t, uint32_t); | |
| static int sdhc_soft_reset(struct sdhc_host *, int); | |
| @@ -235,6 +236,7 @@ static struct sdmmc_chip_functions sdhc_functions = { | |
| .signal_voltage = sdhc_signal_voltage, | |
| .bus_clock_ddr = sdhc_bus_clock_ddr, | |
| .execute_tuning = sdhc_execute_tuning, | |
| + .hw_reset = sdhc_hw_reset, | |
| }; | |
| static int | |
| @@ -1464,6 +1466,16 @@ sdhc_tuning_timer(void *arg) | |
| atomic_swap_uint(&hp->tuning_timer_pending, 1); | |
| } | |
| +static void | |
| +sdhc_hw_reset(sdmmc_chipset_handle_t sch) | |
| +{ | |
| + struct sdhc_host *hp = (struct sdhc_host *)sch; | |
| + struct sdhc_softc *sc = hp->sc; | |
| + | |
| + if (sc->sc_vendor_hw_reset != NULL) | |
| + sc->sc_vendor_hw_reset(sc, hp); | |
| +} | |
| + | |
| static int | |
| sdhc_wait_state(struct sdhc_host *hp, uint32_t mask, uint32_t value) | |
| { | |
| @@ -2380,6 +2392,42 @@ sdhc_host_lock(struct sdhc_host *hp) | |
| return &hp->intr_lock; | |
| } | |
| +uint8_t | |
| +sdhc_host_read_1(struct sdhc_host *hp, int reg) | |
| +{ | |
| + return HREAD1(hp, reg); | |
| +} | |
| + | |
| +uint16_t | |
| +sdhc_host_read_2(struct sdhc_host *hp, int reg) | |
| +{ | |
| + return HREAD2(hp, reg); | |
| +} | |
| + | |
| +uint32_t | |
| +sdhc_host_read_4(struct sdhc_host *hp, int reg) | |
| +{ | |
| + return HREAD4(hp, reg); | |
| +} | |
| + | |
| +void | |
| +sdhc_host_write_1(struct sdhc_host *hp, int reg, uint8_t val) | |
| +{ | |
| + HWRITE1(hp, reg, val); | |
| +} | |
| + | |
| +void | |
| +sdhc_host_write_2(struct sdhc_host *hp, int reg, uint16_t val) | |
| +{ | |
| + HWRITE2(hp, reg, val); | |
| +} | |
| + | |
| +void | |
| +sdhc_host_write_4(struct sdhc_host *hp, int reg, uint32_t val) | |
| +{ | |
| + HWRITE4(hp, reg, val); | |
| +} | |
| + | |
| #ifdef SDHC_DEBUG | |
| void | |
| sdhc_dump_regs(struct sdhc_host *hp) | |
| diff --git a/sys/dev/sdmmc/sdhcvar.h b/sys/dev/sdmmc/sdhcvar.h | |
| index f8a200e..5176f65 100644 | |
| --- a/sys/dev/sdmmc/sdhcvar.h | |
| +++ b/sys/dev/sdmmc/sdhcvar.h | |
| @@ -71,6 +71,7 @@ struct sdhc_softc { | |
| int (*sc_vendor_bus_width)(struct sdhc_softc *, int); | |
| int (*sc_vendor_bus_clock)(struct sdhc_softc *, int); | |
| int (*sc_vendor_transfer_data_dma)(struct sdhc_softc *, struct sdmmc_command *); | |
| + void (*sc_vendor_hw_reset)(struct sdhc_softc *, struct sdhc_host *); | |
| }; | |
| /* Host controller functions called by the attachment driver. */ | |
| @@ -82,5 +83,11 @@ bool sdhc_suspend(device_t, const pmf_qual_t *); | |
| bool sdhc_resume(device_t, const pmf_qual_t *); | |
| bool sdhc_shutdown(device_t, int); | |
| kmutex_t *sdhc_host_lock(struct sdhc_host *); | |
| +uint8_t sdhc_host_read_1(struct sdhc_host *, int); | |
| +uint16_t sdhc_host_read_2(struct sdhc_host *, int); | |
| +uint32_t sdhc_host_read_4(struct sdhc_host *, int); | |
| +void sdhc_host_write_1(struct sdhc_host *, int, uint8_t); | |
| +void sdhc_host_write_2(struct sdhc_host *, int, uint16_t); | |
| +void sdhc_host_write_4(struct sdhc_host *, int, uint32_t); | |
| #endif /* _SDHCVAR_H_ */ | |
| diff --git a/sys/dev/sdmmc/sdmmc.c b/sys/dev/sdmmc/sdmmc.c | |
| index f7ecf5d..cfa0cde 100644 | |
| --- a/sys/dev/sdmmc/sdmmc.c | |
| +++ b/sys/dev/sdmmc/sdmmc.c | |
| @@ -400,6 +400,8 @@ sdmmc_card_attach(struct sdmmc_softc *sc) | |
| CLR(sc->sc_flags, SMF_CARD_ATTACHED); | |
| + sdmmc_chip_hw_reset(sc->sc_sct, sc->sc_sch); | |
| + | |
| /* | |
| * Power up the card (or card stack). | |
| */ | |
| diff --git a/sys/dev/sdmmc/sdmmc_mem.c b/sys/dev/sdmmc/sdmmc_mem.c | |
| index 695fc57..82be651 100644 | |
| --- a/sys/dev/sdmmc/sdmmc_mem.c | |
| +++ b/sys/dev/sdmmc/sdmmc_mem.c | |
| @@ -933,6 +933,7 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct sdmmc_function *sf) | |
| ext_csd[EXT_CSD_STRUCTURE]); | |
| return ENOTSUP; | |
| } | |
| + sf->ext_csd.rev = ext_csd[EXT_CSD_REV]; | |
| sc->sc_transfer_mode = NULL; | |
| if (ISSET(sc->sc_caps, SMC_CAPS_MMC_HS200) && | |
| @@ -1044,6 +1045,11 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct sdmmc_function *sf) | |
| } else { | |
| sc->sc_transfer_mode = NULL; | |
| } | |
| + | |
| + if (sf->ext_csd.rev >= 5) { | |
| + sf->ext_csd.rst_n_function = | |
| + ext_csd[EXT_CSD_RST_N_FUNCTION]; | |
| + } | |
| } else { | |
| if (sc->sc_busclk > sf->csd.tran_speed) | |
| sc->sc_busclk = sf->csd.tran_speed; | |
| diff --git a/sys/dev/sdmmc/sdmmcchip.h b/sys/dev/sdmmc/sdmmcchip.h | |
| index 2619bf9..f6a39c4 100644 | |
| --- a/sys/dev/sdmmc/sdmmcchip.h | |
| +++ b/sys/dev/sdmmc/sdmmcchip.h | |
| @@ -62,6 +62,9 @@ struct sdmmc_chip_functions { | |
| int (*signal_voltage)(sdmmc_chipset_handle_t, int); | |
| int (*bus_clock_ddr)(sdmmc_chipset_handle_t, int, bool); | |
| int (*execute_tuning)(sdmmc_chipset_handle_t, int); | |
| + | |
| + /* hardware reset */ | |
| + void (*hw_reset)(sdmmc_chipset_handle_t); | |
| }; | |
| /* host controller reset */ | |
| @@ -100,6 +103,9 @@ struct sdmmc_chip_functions { | |
| ((tag)->signal_voltage((handle), (voltage))) | |
| #define sdmmc_chip_execute_tuning(tag, handle, timing) \ | |
| ((tag)->execute_tuning ? (tag)->execute_tuning((handle), (timing)) : EINVAL) | |
| +/* hardware reset */ | |
| +#define sdmmc_chip_hw_reset(tag, handle) \ | |
| + ((tag)->hw_reset ? (tag)->hw_reset((handle)) : /*CONSTCOND*/0) | |
| /* clock frequencies for sdmmc_chip_bus_clock() */ | |
| #define SDMMC_SDCLK_OFF 0 | |
| diff --git a/sys/dev/sdmmc/sdmmcreg.h b/sys/dev/sdmmc/sdmmcreg.h | |
| index 0728c09..fca8c27 100644 | |
| --- a/sys/dev/sdmmc/sdmmcreg.h | |
| +++ b/sys/dev/sdmmc/sdmmcreg.h | |
| @@ -118,6 +118,7 @@ | |
| #define SD_ARG_BUS_WIDTH_4 2 | |
| /* EXT_CSD fields */ | |
| +#define EXT_CSD_RST_N_FUNCTION 162 /* R/WO */ | |
| #define EXT_CSD_BUS_WIDTH 183 /* WO */ | |
| #define EXT_CSD_HS_TIMING 185 /* R/W */ | |
| #define EXT_CSD_REV 192 /* RO */ | |
| @@ -155,6 +156,12 @@ | |
| #define EXT_CSD_CARD_TYPE_52M_V12 0x0b | |
| #define EXT_CSD_CARD_TYPE_52M_V12_18 0x0f | |
| +/* EXT_CSD_RST_N_FUNCTION */ | |
| +#define EXT_CSD_RST_N_TMP_DISABLED 0x00 | |
| +#define EXT_CSD_RST_N_PERM_ENABLED 0x01 | |
| +#define EXT_CSD_RST_N_PERM_DISABLED 0x02 | |
| +#define EXT_CSD_RST_N_MASK 0x03 | |
| + | |
| /* MMC_SWITCH access mode */ | |
| #define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ | |
| #define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */ | |
| diff --git a/sys/dev/sdmmc/sdmmcvar.h b/sys/dev/sdmmc/sdmmcvar.h | |
| index 0bce458..961c0e1 100644 | |
| --- a/sys/dev/sdmmc/sdmmcvar.h | |
| +++ b/sys/dev/sdmmc/sdmmcvar.h | |
| @@ -49,6 +49,11 @@ struct sdmmc_csd { | |
| /* ... */ | |
| }; | |
| +struct sdmmc_ext_csd { | |
| + uint8_t rev; | |
| + uint8_t rst_n_function; /* RST_n_FUNCTION */ | |
| +}; | |
| + | |
| struct sdmmc_cid { | |
| int mid; /* manufacturer identification number */ | |
| int oid; /* OEM/product identification number */ | |
| @@ -185,6 +190,7 @@ struct sdmmc_function { | |
| struct sdmmc_cis cis; /* decoded CIS */ | |
| /* SD/MMC memory card members */ | |
| struct sdmmc_csd csd; /* decoded CSD value */ | |
| + struct sdmmc_ext_csd ext_csd; /* decoded EXT_CSD value */ | |
| struct sdmmc_cid cid; /* decoded CID value */ | |
| sdmmc_response raw_cid; /* temp. storage for decoding */ | |
| uint32_t raw_scr[2]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment