svn commit: r359925 - head/sys/arm/allwinner

Emmanuel Vadot manu at FreeBSD.org
Tue Apr 14 16:34:14 UTC 2020


Author: manu
Date: Tue Apr 14 16:34:13 2020
New Revision: 359925
URL: https://svnweb.freebsd.org/changeset/base/359925

Log:
  arm: allwinner: aw_mmc: Use the mmc_fdt_helper
  
  The fdt properties are now parsed via the help of mmc_fdt_helper functions.
  This also adds card detection.
  Note that on some boards (like the Pine64) card detection is broken due to
  a missing resistor on the cd pin.
  
  MFC after:	1 month
  Differential Revision:	https://reviews.freebsd.org/D23268

Modified:
  head/sys/arm/allwinner/aw_mmc.c

Modified: head/sys/arm/allwinner/aw_mmc.c
==============================================================================
--- head/sys/arm/allwinner/aw_mmc.c	Tue Apr 14 16:30:54 2020	(r359924)
+++ head/sys/arm/allwinner/aw_mmc.c	Tue Apr 14 16:34:13 2020	(r359925)
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/resource.h>
 #include <sys/rman.h>
 #include <sys/sysctl.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
 
 #include <machine/bus.h>
 
@@ -49,6 +51,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/mmc/bridge.h>
 #include <dev/mmc/mmcbrvar.h>
+#include <dev/mmc/mmc_fdt_helpers.h>
 
 #include <arm/allwinner/aw_mmc.h>
 #include <dev/extres/clk/clk.h>
@@ -122,6 +125,7 @@ struct aw_mmc_softc {
 	int			aw_timeout;
 	struct callout		aw_timeoutc;
 	struct mmc_host		aw_host;
+	struct mmc_fdt_helper	mmc_helper;
 #ifdef MMCCAM
 	union ccb *		ccb;
 	struct cam_devq *	devq;
@@ -136,9 +140,8 @@ struct aw_mmc_softc {
 	uint32_t		aw_intr;
 	uint32_t		aw_intr_wait;
 	void *			aw_intrhand;
-	regulator_t		aw_reg_vmmc;
-	regulator_t		aw_reg_vqmmc;
 	unsigned int		aw_clock;
+	device_t		child;
 
 	/* Fields required for DMA access. */
 	bus_addr_t	  	aw_dma_desc_phys;
@@ -164,6 +167,7 @@ static int aw_mmc_reset(struct aw_mmc_softc *);
 static int aw_mmc_init(struct aw_mmc_softc *);
 static void aw_mmc_intr(void *);
 static int aw_mmc_update_clock(struct aw_mmc_softc *, uint32_t);
+static void aw_mmc_helper_cd_handler(device_t, bool);
 
 static void aw_mmc_print_error(uint32_t);
 static int aw_mmc_update_ios(device_t, device_t);
@@ -360,6 +364,40 @@ aw_mmc_cam_request(struct aw_mmc_softc *sc, union ccb 
 }
 #endif /* MMCCAM */
 
+static void
+aw_mmc_helper_cd_handler(device_t dev, bool present)
+{
+	struct aw_mmc_softc *sc;
+
+	sc = device_get_softc(dev);
+	AW_MMC_LOCK(sc);
+	if (present) {
+		if (sc->child == NULL) {
+			if (bootverbose)
+				device_printf(sc->aw_dev, "Card inserted\n");
+
+			sc->child = device_add_child(sc->aw_dev, "mmc", -1);
+			AW_MMC_UNLOCK(sc);
+			if (sc->child) {
+				device_set_ivars(sc->child, sc);
+				(void)device_probe_and_attach(sc->child);
+			}
+		} else
+			AW_MMC_UNLOCK(sc);
+	} else {
+		/* Card isn't present, detach if necessary */
+		if (sc->child != NULL) {
+			if (bootverbose)
+				device_printf(sc->aw_dev, "Card removed\n");
+
+			AW_MMC_UNLOCK(sc);
+			device_delete_child(sc->aw_dev, sc->child);
+			sc->child = NULL;
+		} else
+			AW_MMC_UNLOCK(sc);
+	}
+}
+
 static int
 aw_mmc_probe(device_t dev)
 {
@@ -377,15 +415,11 @@ aw_mmc_probe(device_t dev)
 static int
 aw_mmc_attach(device_t dev)
 {
-	device_t child;
 	struct aw_mmc_softc *sc;
 	struct sysctl_ctx_list *ctx;
 	struct sysctl_oid_list *tree;
-	uint32_t bus_width, max_freq;
-	phandle_t node;
 	int error;
 
-	node = ofw_bus_get_node(dev);
 	sc = device_get_softc(dev);
 	sc->aw_dev = dev;
 
@@ -399,7 +433,7 @@ aw_mmc_attach(device_t dev)
 		return (ENXIO);
 	}
 	if (bus_setup_intr(dev, sc->aw_res[AW_MMC_IRQRES],
-	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, aw_mmc_intr, sc,
+	    INTR_TYPE_NET | INTR_MPSAFE, NULL, aw_mmc_intr, sc,
 	    &sc->aw_intrhand)) {
 		bus_release_resources(dev, aw_mmc_res_spec, sc->aw_res);
 		device_printf(dev, "cannot setup interrupt handler\n");
@@ -463,47 +497,15 @@ aw_mmc_attach(device_t dev)
 		goto fail;
 	}
 
-	if (OF_getencprop(node, "bus-width", &bus_width, sizeof(uint32_t)) <= 0)
-		bus_width = 4;
-
-	if (regulator_get_by_ofw_property(dev, 0, "vmmc-supply",
-	    &sc->aw_reg_vmmc) == 0) {
-		if (bootverbose)
-			device_printf(dev, "vmmc-supply regulator found\n");
-	}
-	if (regulator_get_by_ofw_property(dev, 0, "vqmmc-supply",
-	    &sc->aw_reg_vqmmc) == 0 && bootverbose) {
-		if (bootverbose)
-			device_printf(dev, "vqmmc-supply regulator found\n");
-	}
-
+	/* Set some defaults for freq and supported mode */
 	sc->aw_host.f_min = 400000;
-
-	if (OF_getencprop(node, "max-frequency", &max_freq,
-	    sizeof(uint32_t)) <= 0)
-		max_freq = 52000000;
-	sc->aw_host.f_max = max_freq;
-
+	sc->aw_host.f_max = 52000000;
 	sc->aw_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
-	sc->aw_host.caps = MMC_CAP_HSPEED | MMC_CAP_UHS_SDR12 |
-			   MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
-			   MMC_CAP_UHS_DDR50 | MMC_CAP_MMC_DDR52;
+	sc->aw_host.caps |= MMC_CAP_HSPEED | MMC_CAP_SIGNALING_330;
+	mmc_fdt_parse(dev, 0, &sc->mmc_helper, &sc->aw_host);
+	mmc_fdt_gpio_setup(dev, 0, &sc->mmc_helper, aw_mmc_helper_cd_handler);
 
-	if (sc->aw_reg_vqmmc != NULL) {
-		if (regulator_check_voltage(sc->aw_reg_vqmmc, 1800000) == 0)
-			sc->aw_host.caps |= MMC_CAP_SIGNALING_180;
-		if (regulator_check_voltage(sc->aw_reg_vqmmc, 3300000) == 0)
-			sc->aw_host.caps |= MMC_CAP_SIGNALING_330;
-	} else
-		sc->aw_host.caps |= MMC_CAP_SIGNALING_330;
-
-	if (bus_width >= 4)
-		sc->aw_host.caps |= MMC_CAP_4_BIT_DATA;
-	if (bus_width >= 8)
-		sc->aw_host.caps |= MMC_CAP_8_BIT_DATA;
-
 #ifdef MMCCAM
-	child = NULL; /* Not used by MMCCAM, need to silence compiler warnings */
 	sc->ccb = NULL;
 	if ((sc->devq = cam_simq_alloc(1)) == NULL) {
 		goto fail;
@@ -530,18 +532,8 @@ aw_mmc_attach(device_t dev)
 	}
 
 	mtx_unlock(&sc->sim_mtx);
-#else /* !MMCCAM */
-	child = device_add_child(dev, "mmc", -1);
-	if (child == NULL) {
-		device_printf(dev, "attaching MMC bus failed!\n");
-		goto fail;
-	}
-	if (device_probe_and_attach(child) != 0) {
-		device_printf(dev, "attaching MMC child failed!\n");
-		device_delete_child(dev, child);
-		goto fail;
-	}
 #endif /* MMCCAM */
+
 	return (0);
 
 fail:
@@ -1301,7 +1293,7 @@ aw_mmc_switch_vccq(device_t bus, device_t child)
 
 	sc = device_get_softc(bus);
 
-	if (sc->aw_reg_vqmmc == NULL)
+	if (sc->mmc_helper.vqmmc_supply == NULL)
 		return EOPNOTSUPP;
 
 	switch (sc->aw_host.ios.vccq) {
@@ -1315,7 +1307,7 @@ aw_mmc_switch_vccq(device_t bus, device_t child)
 		return EINVAL;
 	}
 
-	err = regulator_set_voltage(sc->aw_reg_vqmmc, uvolt, uvolt);
+	err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply, uvolt, uvolt);
 	if (err != 0) {
 		device_printf(sc->aw_dev,
 		    "Cannot set vqmmc to %d<->%d\n",
@@ -1360,10 +1352,10 @@ aw_mmc_update_ios(device_t bus, device_t child)
 		if (bootverbose)
 			device_printf(sc->aw_dev, "Powering down sd/mmc\n");
 
-		if (sc->aw_reg_vmmc)
-			regulator_disable(sc->aw_reg_vmmc);
-		if (sc->aw_reg_vqmmc)
-			regulator_disable(sc->aw_reg_vqmmc);
+		if (sc->mmc_helper.vmmc_supply)
+			regulator_disable(sc->mmc_helper.vmmc_supply);
+		if (sc->mmc_helper.vqmmc_supply)
+			regulator_disable(sc->mmc_helper.vqmmc_supply);
 
 		aw_mmc_reset(sc);
 		break;
@@ -1371,10 +1363,10 @@ aw_mmc_update_ios(device_t bus, device_t child)
 		if (bootverbose)
 			device_printf(sc->aw_dev, "Powering up sd/mmc\n");
 
-		if (sc->aw_reg_vmmc)
-			regulator_enable(sc->aw_reg_vmmc);
-		if (sc->aw_reg_vqmmc)
-			regulator_enable(sc->aw_reg_vqmmc);
+		if (sc->mmc_helper.vmmc_supply)
+			regulator_enable(sc->mmc_helper.vmmc_supply);
+		if (sc->mmc_helper.vqmmc_supply)
+			regulator_enable(sc->mmc_helper.vqmmc_supply);
 		aw_mmc_init(sc);
 		break;
 	};
@@ -1450,8 +1442,11 @@ aw_mmc_update_ios(device_t bus, device_t child)
 static int
 aw_mmc_get_ro(device_t bus, device_t child)
 {
+	struct aw_mmc_softc *sc;
 
-	return (0);
+	sc = device_get_softc(bus);
+
+	return (mmc_fdt_gpio_get_readonly(&sc->mmc_helper));
 }
 
 static int


More information about the svn-src-head mailing list