Module Name:    src
Committed By:   nonaka
Date:           Fri Feb 17 10:51:48 UTC 2017

Modified Files:
        src/sys/dev/acpi: sdhc_acpi.c
        src/sys/dev/pci: sdhc_pci.c
        src/sys/dev/sdmmc: sdhc.c sdhcvar.h sdmmc.c sdmmc_mem.c sdmmcchip.h
            sdmmcreg.h sdmmcvar.h

Log Message:
sdhc(4): hardware reset support for Intel eMMC controller


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/acpi/sdhc_acpi.c
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/pci/sdhc_pci.c
cvs rdiff -u -r1.98 -r1.99 src/sys/dev/sdmmc/sdhc.c
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/sdmmc/sdhcvar.h
cvs rdiff -u -r1.33 -r1.34 src/sys/dev/sdmmc/sdmmc.c
cvs rdiff -u -r1.54 -r1.55 src/sys/dev/sdmmc/sdmmc_mem.c
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/sdmmc/sdmmcchip.h
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/sdmmc/sdmmcreg.h
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/sdmmc/sdmmcvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/sdhc_acpi.c
diff -u src/sys/dev/acpi/sdhc_acpi.c:1.3 src/sys/dev/acpi/sdhc_acpi.c:1.4
--- src/sys/dev/acpi/sdhc_acpi.c:1.3	Thu Aug 11 01:54:30 2016
+++ src/sys/dev/acpi/sdhc_acpi.c	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhc_acpi.c,v 1.3 2016/08/11 01:54:30 nonaka Exp $	*/
+/*	$NetBSD: sdhc_acpi.c,v 1.4 2017/02/17 10:51:48 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc_acpi.c,v 1.3 2016/08/11 01:54:30 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc_acpi.c,v 1.4 2017/02/17 10:51:48 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -50,6 +50,9 @@ static bool	sdhc_acpi_resume(device_t, c
 
 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_
 	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
 {
 	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
 		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,22 +181,23 @@ sdhc_acpi_attach(device_t parent, device
 	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;
 	}
 
 	/* Enable DMA transfer */
 	sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
 
-	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,
@@ -154,15 +208,23 @@ sdhc_acpi_attach(device_t parent, device
 	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
@@ -173,9 +235,6 @@ sdhc_acpi_detach(device_t self, int flag
 
 	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;
@@ -187,6 +246,12 @@ sdhc_acpi_detach(device_t self, int flag
 	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;
 }
 
@@ -215,3 +280,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);
+}

Index: src/sys/dev/pci/sdhc_pci.c
diff -u src/sys/dev/pci/sdhc_pci.c:1.12 src/sys/dev/pci/sdhc_pci.c:1.13
--- src/sys/dev/pci/sdhc_pci.c:1.12	Sun Aug  9 13:27:48 2015
+++ src/sys/dev/pci/sdhc_pci.c	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhc_pci.c,v 1.12 2015/08/09 13:27:48 mlelstv Exp $	*/
+/*	$NetBSD: sdhc_pci.c,v 1.13 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdhc_pci.c,v 1.7 2007/10/30 18:13:45 chl Exp $	*/
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.12 2015/08/09 13:27:48 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.13 2017/02/17 10:51:48 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -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_
 		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(str
 	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);
+}

Index: src/sys/dev/sdmmc/sdhc.c
diff -u src/sys/dev/sdmmc/sdhc.c:1.98 src/sys/dev/sdmmc/sdhc.c:1.99
--- src/sys/dev/sdmmc/sdhc.c:1.98	Fri Feb 17 10:50:43 2017
+++ src/sys/dev/sdmmc/sdhc.c	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhc.c,v 1.98 2017/02/17 10:50:43 nonaka Exp $	*/
+/*	$NetBSD: sdhc.c,v 1.99 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $	*/
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.98 2017/02/17 10:50:43 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.99 2017/02/17 10:51:48 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -192,6 +192,7 @@ static int	sdhc_signal_voltage(sdmmc_chi
 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_
 	.signal_voltage = sdhc_signal_voltage,
 	.bus_clock_ddr = sdhc_bus_clock_ddr,
 	.execute_tuning = sdhc_execute_tuning,
+	.hw_reset = sdhc_hw_reset,
 };
 
 static int
@@ -1479,6 +1481,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)
 {
@@ -2402,6 +2414,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)

Index: src/sys/dev/sdmmc/sdhcvar.h
diff -u src/sys/dev/sdmmc/sdhcvar.h:1.27 src/sys/dev/sdmmc/sdhcvar.h:1.28
--- src/sys/dev/sdmmc/sdhcvar.h:1.27	Sat Jan  7 15:05:08 2017
+++ src/sys/dev/sdmmc/sdhcvar.h	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhcvar.h,v 1.27 2017/01/07 15:05:08 kiyohara Exp $	*/
+/*	$NetBSD: sdhcvar.h,v 1.28 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $	*/
 
 /*
@@ -73,6 +73,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. */
@@ -84,5 +85,11 @@ bool	sdhc_suspend(device_t, const pmf_qu
 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_ */

Index: src/sys/dev/sdmmc/sdmmc.c
diff -u src/sys/dev/sdmmc/sdmmc.c:1.33 src/sys/dev/sdmmc/sdmmc.c:1.34
--- src/sys/dev/sdmmc/sdmmc.c:1.33	Tue Dec 22 09:55:38 2015
+++ src/sys/dev/sdmmc/sdmmc.c	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmc.c,v 1.33 2015/12/22 09:55:38 mlelstv Exp $	*/
+/*	$NetBSD: sdmmc.c,v 1.34 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdmmc.c,v 1.18 2009/01/09 10:58:38 jsg Exp $	*/
 
 /*
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.33 2015/12/22 09:55:38 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.34 2017/02/17 10:51:48 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -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).
 	 */

Index: src/sys/dev/sdmmc/sdmmc_mem.c
diff -u src/sys/dev/sdmmc/sdmmc_mem.c:1.54 src/sys/dev/sdmmc/sdmmc_mem.c:1.55
--- src/sys/dev/sdmmc/sdmmc_mem.c:1.54	Fri Feb 17 10:50:43 2017
+++ src/sys/dev/sdmmc/sdmmc_mem.c	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmc_mem.c,v 1.54 2017/02/17 10:50:43 nonaka Exp $	*/
+/*	$NetBSD: sdmmc_mem.c,v 1.55 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -45,7 +45,7 @@
 /* Routines for SD/MMC memory cards. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.54 2017/02/17 10:50:43 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.55 2017/02/17 10:51:48 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -934,6 +934,7 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
 				ext_csd[EXT_CSD_STRUCTURE]);
 			return ENOTSUP;
 		}
+		sf->ext_csd.rev = ext_csd[EXT_CSD_REV];
 
 		if (ISSET(sc->sc_caps, SMC_CAPS_MMC_HS200) &&
 		    ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_F_HS200_1_8V) {
@@ -1088,6 +1089,11 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
 				return error;
 			}
 		}
+
+		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;

Index: src/sys/dev/sdmmc/sdmmcchip.h
diff -u src/sys/dev/sdmmc/sdmmcchip.h:1.8 src/sys/dev/sdmmc/sdmmcchip.h:1.9
--- src/sys/dev/sdmmc/sdmmcchip.h:1.8	Fri Feb 17 10:50:43 2017
+++ src/sys/dev/sdmmc/sdmmcchip.h	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmcchip.h,v 1.8 2017/02/17 10:50:43 nonaka Exp $	*/
+/*	$NetBSD: sdmmcchip.h,v 1.9 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdmmcchip.h,v 1.3 2007/05/31 10:09:01 uwe Exp $	*/
 
 /*
@@ -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 ? (tag)->signal_voltage((handle), (voltage)) : EINVAL)
 #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

Index: src/sys/dev/sdmmc/sdmmcreg.h
diff -u src/sys/dev/sdmmc/sdmmcreg.h:1.28 src/sys/dev/sdmmc/sdmmcreg.h:1.29
--- src/sys/dev/sdmmc/sdmmcreg.h:1.28	Fri Feb 17 10:47:09 2017
+++ src/sys/dev/sdmmc/sdmmcreg.h	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmcreg.h,v 1.28 2017/02/17 10:47:09 nonaka Exp $	*/
+/*	$NetBSD: sdmmcreg.h,v 1.29 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -115,6 +115,7 @@
 #define SD_ARG_BUS_WIDTH_4		2
 
 /* EXT_CSD fields */
+#define EXT_CSD_RST_N_FUNCTION		162	/* R/W */
 #define EXT_CSD_BUS_WIDTH		183	/* W/E_P */
 #define EXT_CSD_HS_TIMING		185	/* R/W/E_P */
 #define EXT_CSD_REV			192	/* R */
@@ -155,6 +156,12 @@
 #define EXT_CSD_CARD_TYPE_F_HS400_1_8V	(1 << 6) /* HS400 DDR 200 MHz 1.8V */
 #define EXT_CSD_CARD_TYPE_F_HS400_1_2V	(1 << 7) /* HS400 DDR 200 MHz 1.2V */
 
+/* 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 */

Index: src/sys/dev/sdmmc/sdmmcvar.h
diff -u src/sys/dev/sdmmc/sdmmcvar.h:1.22 src/sys/dev/sdmmc/sdmmcvar.h:1.23
--- src/sys/dev/sdmmc/sdmmcvar.h:1.22	Fri Feb 17 10:49:47 2017
+++ src/sys/dev/sdmmc/sdmmcvar.h	Fri Feb 17 10:51:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmcvar.h,v 1.22 2017/02/17 10:49:47 nonaka Exp $	*/
+/*	$NetBSD: sdmmcvar.h,v 1.23 2017/02/17 10:51:48 nonaka Exp $	*/
 /*	$OpenBSD: sdmmcvar.h,v 1.13 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -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];

Reply via email to