aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/mmc
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2019-12-11 18:41:13 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2019-12-11 18:41:13 +0000
commit87dc015dbf35da3ff8b484602f631bc2dd1a2784 (patch)
tree12ac6c5366c705c969066a2423bb347aebbb2aa2 /sys/dev/mmc
parent6fe4e8bdbd52c3d45cba127536aba065ed6f6155 (diff)
Notes
Diffstat (limited to 'sys/dev/mmc')
-rw-r--r--sys/dev/mmc/host/dwmmc.c61
-rw-r--r--sys/dev/mmc/host/dwmmc_rockchip.c1
-rw-r--r--sys/dev/mmc/host/dwmmc_var.h2
3 files changed, 63 insertions, 1 deletions
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
index a6b01f9ad4f0..38e5b63fc6ee 100644
--- a/sys/dev/mmc/host/dwmmc.c
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -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,10 +677,53 @@ 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
dwmmc_setup_bus(struct dwmmc_softc *sc, int freq)
{
diff --git a/sys/dev/mmc/host/dwmmc_rockchip.c b/sys/dev/mmc/host/dwmmc_rockchip.c
index b0452da3d405..d21e72d88aef 100644
--- a/sys/dev/mmc/host/dwmmc_rockchip.c
+++ b/sys/dev/mmc/host/dwmmc_rockchip.c
@@ -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
};
diff --git a/sys/dev/mmc/host/dwmmc_var.h b/sys/dev/mmc/host/dwmmc_var.h
index ae4f547a88bd..52956bfc3566 100644
--- a/sys/dev/mmc/host/dwmmc_var.h
+++ b/sys/dev/mmc/host/dwmmc_var.h
@@ -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