Date: Wed, 11 Dec 2019 18:50:23 +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: r355627 - head/sys/dev/mmc/host Message-ID: <201912111850.xBBIoNDT020038@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: manu Date: Wed Dec 11 18:50:23 2019 New Revision: 355627 URL: https://svnweb.freebsd.org/changeset/base/355627 Log: dwmmc: Handle the card detect interrupt The driver used to always add the mmc device as it's child even it no card was detected. Add a function that will detect if the card is present or not and that will attach/detach the mmc device. The function is either call on attach (as we won't have the interrupt fired) or from two taskqueues. The first taskqueue will directly call the function when the sdcard was present and is now removed and the other one will delay a bit the attach when we didn't had a card and now have one. This is mostly based on comments from the sdhci driver where it describe a situation when the CD pin is detected before the others pins are connected. MFC after: 1 month Modified: head/sys/dev/mmc/host/dwmmc.c head/sys/dev/mmc/host/dwmmc_altera.c head/sys/dev/mmc/host/dwmmc_hisi.c head/sys/dev/mmc/host/dwmmc_rockchip.c head/sys/dev/mmc/host/dwmmc_samsung.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:43:39 2019 (r355626) +++ head/sys/dev/mmc/host/dwmmc.c Wed Dec 11 18:50:23 2019 (r355627) @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/rman.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> #include <dev/mmc/bridge.h> #include <dev/mmc/mmcbrvar.h> @@ -127,6 +129,7 @@ static int dma_done(struct dwmmc_softc *, struct mmc_c static int dma_stop(struct dwmmc_softc *); static void pio_read(struct dwmmc_softc *, struct mmc_command *); static void pio_write(struct dwmmc_softc *, struct mmc_command *); +static void dwmmc_handle_card_present(struct dwmmc_softc *sc, bool is_present); static struct resource_spec dwmmc_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, @@ -374,7 +377,8 @@ dwmmc_intr(void *arg) sc->dto_rcvd = 1; if (reg & SDMMC_INTMASK_CD) { - /* XXX: Handle card detect */ + dwmmc_handle_card_present(sc, + READ4(sc, SDMMC_CDETECT) == 0 ? true : false); } } @@ -407,6 +411,56 @@ dwmmc_intr(void *arg) DWMMC_UNLOCK(sc); } +static void +dwmmc_handle_card_present(struct dwmmc_softc *sc, bool is_present) +{ + bool was_present; + + was_present = sc->child != NULL; + + if (!was_present && is_present) { + taskqueue_enqueue_timeout(taskqueue_swi_giant, + &sc->card_delayed_task, -(hz / 2)); + } else if (was_present && !is_present) { + taskqueue_enqueue(taskqueue_swi_giant, &sc->card_task); + } +} + +static void +dwmmc_card_task(void *arg, int pending __unused) +{ + struct dwmmc_softc *sc = arg; + + DWMMC_LOCK(sc); + + if (READ4(sc, SDMMC_CDETECT) == 0) { + if (sc->child == NULL) { + if (bootverbose) + device_printf(sc->dev, "Card inserted\n"); + + sc->child = device_add_child(sc->dev, "mmc", -1); + DWMMC_UNLOCK(sc); + if (sc->child) { + device_set_ivars(sc->child, sc); + (void)device_probe_and_attach(sc->child); + } + } else + DWMMC_UNLOCK(sc); + + } else { + /* Card isn't present, detach if necessary */ + if (sc->child != NULL) { + if (bootverbose) + device_printf(sc->dev, "Card removed\n"); + + DWMMC_UNLOCK(sc); + device_delete_child(sc->dev, sc->child); + sc->child = NULL; + } else + DWMMC_UNLOCK(sc); + } +} + static int parse_fdt(struct dwmmc_softc *sc) { @@ -677,8 +731,17 @@ dwmmc_attach(device_t dev) sc->host.caps |= MMC_CAP_HSPEED; sc->host.caps |= MMC_CAP_SIGNALING_330; - sc->child = device_add_child(dev, "mmc", -1); - return (bus_generic_attach(dev)); + TASK_INIT(&sc->card_task, 0, dwmmc_card_task, sc); + TIMEOUT_TASK_INIT(taskqueue_swi_giant, &sc->card_delayed_task, 0, + dwmmc_card_task, sc); + + /* + * Schedule a card detection as we won't get an interrupt + * if the card is inserted when we attach + */ + dwmmc_card_task(sc, 0); + + return (0); } int @@ -693,7 +756,9 @@ dwmmc_detach(device_t dev) if (ret != 0) return (ret); - DWMMC_LOCK_DESTROY(sc); + taskqueue_drain(taskqueue_swi_giant, &sc->card_task); + taskqueue_drain_timeout(taskqueue_swi_giant, &sc->card_delayed_task); + if (sc->intr_cookie != NULL) { ret = bus_teardown_intr(dev, sc->res[1], sc->intr_cookie); if (ret != 0) @@ -706,6 +771,8 @@ dwmmc_detach(device_t dev) if (ret != 0) return (ret); } + + DWMMC_LOCK_DESTROY(sc); #ifdef EXT_RESOURCES if (sc->hwreset != NULL && hwreset_deassert(sc->hwreset) != 0) Modified: head/sys/dev/mmc/host/dwmmc_altera.c ============================================================================== --- head/sys/dev/mmc/host/dwmmc_altera.c Wed Dec 11 18:43:39 2019 (r355626) +++ head/sys/dev/mmc/host/dwmmc_altera.c Wed Dec 11 18:50:23 2019 (r355627) @@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/bus.h> #include <sys/module.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> #include <machine/bus.h> Modified: head/sys/dev/mmc/host/dwmmc_hisi.c ============================================================================== --- head/sys/dev/mmc/host/dwmmc_hisi.c Wed Dec 11 18:43:39 2019 (r355626) +++ head/sys/dev/mmc/host/dwmmc_hisi.c Wed Dec 11 18:50:23 2019 (r355627) @@ -32,6 +32,8 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/bus.h> #include <sys/module.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> #include <machine/bus.h> Modified: head/sys/dev/mmc/host/dwmmc_rockchip.c ============================================================================== --- head/sys/dev/mmc/host/dwmmc_rockchip.c Wed Dec 11 18:43:39 2019 (r355626) +++ head/sys/dev/mmc/host/dwmmc_rockchip.c Wed Dec 11 18:50:23 2019 (r355627) @@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/bus.h> #include <sys/module.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> #include <machine/bus.h> Modified: head/sys/dev/mmc/host/dwmmc_samsung.c ============================================================================== --- head/sys/dev/mmc/host/dwmmc_samsung.c Wed Dec 11 18:43:39 2019 (r355626) +++ head/sys/dev/mmc/host/dwmmc_samsung.c Wed Dec 11 18:50:23 2019 (r355627) @@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/bus.h> #include <sys/module.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> #include <machine/bus.h> Modified: head/sys/dev/mmc/host/dwmmc_var.h ============================================================================== --- head/sys/dev/mmc/host/dwmmc_var.h Wed Dec 11 18:43:39 2019 (r355626) +++ head/sys/dev/mmc/host/dwmmc_var.h Wed Dec 11 18:50:23 2019 (r355627) @@ -62,6 +62,8 @@ struct dwmmc_softc { uint32_t pwren_inverted; u_int desc_count; device_t child; + struct task card_task; /* Card presence check task */ + struct timeout_task card_delayed_task;/* Card insert delayed task */ int (*update_ios)(struct dwmmc_softc *sc, struct mmc_ios *ios);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912111850.xBBIoNDT020038>