Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Dec 2019 18:41:13 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r355625 - head/sys/dev/mmc/host
Message-ID:  <201912111841.xBBIfDZY016000@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Wed Dec 11 18:41:13 2019
New Revision: 355625
URL: https://svnweb.freebsd.org/changeset/base/355625

Log:
  dwmmc: Add a detach method
  
  This method will disable the regulators, clocks and assert the reset of
  the module. It will also detach it's children (the mmc device) and release
  it's resources.
  While here enable the regulators on attach as we need them to power up
  the sdcard or emmc.
  
  MFC after:	1 month

Modified:
  head/sys/dev/mmc/host/dwmmc.c
  head/sys/dev/mmc/host/dwmmc_rockchip.c
  head/sys/dev/mmc/host/dwmmc_var.h

Modified: head/sys/dev/mmc/host/dwmmc.c
==============================================================================
--- head/sys/dev/mmc/host/dwmmc.c	Wed Dec 11 18:39:05 2019	(r355624)
+++ head/sys/dev/mmc/host/dwmmc.c	Wed Dec 11 18:41:13 2019	(r355625)
@@ -537,6 +537,22 @@ parse_fdt(struct dwmmc_softc *sc)
 		clk_get_freq(sc->ciu, &sc->bus_hz);
 	}
 
+	/* Enable regulators */
+	if (sc->vmmc != NULL) {
+		error = regulator_enable(sc->vmmc);
+		if (error != 0) {
+			device_printf(sc->dev, "Cannot enable vmmc regulator\n");
+			goto fail;
+		}
+	}
+	if (sc->vqmmc != NULL) {
+		error = regulator_enable(sc->vqmmc);
+		if (error != 0) {
+			device_printf(sc->dev, "Cannot enable vqmmc regulator\n");
+			goto fail;
+		}
+	}
+
 	/* Take dwmmc out of reset */
 	if (sc->hwreset != NULL) {
 		error = hwreset_deassert(sc->hwreset);
@@ -661,8 +677,51 @@ dwmmc_attach(device_t dev)
 	sc->host.caps |= MMC_CAP_HSPEED;
 	sc->host.caps |= MMC_CAP_SIGNALING_330;
 
-	device_add_child(dev, "mmc", -1);
+	sc->child = device_add_child(dev, "mmc", -1);
 	return (bus_generic_attach(dev));
+}
+
+int
+dwmmc_detach(device_t dev)
+{
+	struct dwmmc_softc *sc;
+	int ret;
+
+	sc = device_get_softc(dev);
+
+	ret = bus_generic_detach(dev);
+	if (ret != 0)
+		return (ret);
+
+	DWMMC_LOCK_DESTROY(sc);
+	if (sc->intr_cookie != NULL) {
+		ret = bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
+		if (ret != 0)
+			return (ret);
+	}
+	bus_release_resources(dev, dwmmc_spec, sc->res);
+
+	if (sc->child) {
+		ret = device_delete_child(dev, sc->child);
+		if (ret != 0)
+			return (ret);
+	}
+
+#ifdef EXT_RESOURCES
+	if (sc->hwreset != NULL && hwreset_deassert(sc->hwreset) != 0)
+		device_printf(sc->dev, "cannot deassert reset\n");
+	if (sc->biu != NULL && clk_disable(sc->biu) != 0)
+		device_printf(sc->dev, "cannot disable biu clock\n");
+	if (sc->ciu != NULL && clk_disable(sc->ciu) != 0)
+			device_printf(sc->dev, "cannot disable ciu clock\n");
+
+	if (sc->vmmc && regulator_disable(sc->vmmc) != 0)
+		device_printf(sc->dev, "Cannot disable vmmc regulator\n");
+	if (sc->vqmmc && regulator_disable(sc->vqmmc) != 0)
+		device_printf(sc->dev, "Cannot disable vqmmc regulator\n");
+#endif
+
+	return (0);
 }
 
 static int

Modified: head/sys/dev/mmc/host/dwmmc_rockchip.c
==============================================================================
--- head/sys/dev/mmc/host/dwmmc_rockchip.c	Wed Dec 11 18:39:05 2019	(r355624)
+++ head/sys/dev/mmc/host/dwmmc_rockchip.c	Wed Dec 11 18:41:13 2019	(r355625)
@@ -133,6 +133,7 @@ static device_method_t rockchip_dwmmc_methods[] = {
 	/* bus interface */
 	DEVMETHOD(device_probe, rockchip_dwmmc_probe),
 	DEVMETHOD(device_attach, rockchip_dwmmc_attach),
+	DEVMETHOD(device_detach, dwmmc_detach),
 
 	DEVMETHOD_END
 };

Modified: head/sys/dev/mmc/host/dwmmc_var.h
==============================================================================
--- head/sys/dev/mmc/host/dwmmc_var.h	Wed Dec 11 18:39:05 2019	(r355624)
+++ head/sys/dev/mmc/host/dwmmc_var.h	Wed Dec 11 18:41:13 2019	(r355625)
@@ -61,6 +61,7 @@ struct dwmmc_softc {
 	uint32_t		use_pio;
 	uint32_t		pwren_inverted;
 	u_int			desc_count;
+	device_t		child;
 
 	int			(*update_ios)(struct dwmmc_softc *sc, struct mmc_ios *ios);
 
@@ -94,5 +95,6 @@ struct dwmmc_softc {
 DECLARE_CLASS(dwmmc_driver);
 
 int dwmmc_attach(device_t);
+int dwmmc_detach(device_t);
 
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912111841.xBBIfDZY016000>