From owner-svn-src-all@freebsd.org Wed Dec 11 18:50:25 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 7184B1DDDF8; Wed, 11 Dec 2019 18:50:25 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47Y5bP28Yvz4VBD; Wed, 11 Dec 2019 18:50:25 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4521FF925; Wed, 11 Dec 2019 18:50:25 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xBBIoPFm020044; Wed, 11 Dec 2019 18:50:25 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xBBIoNDT020038; Wed, 11 Dec 2019 18:50:23 GMT (envelope-from manu@FreeBSD.org) Message-Id: <201912111850.xBBIoNDT020038@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Wed, 11 Dec 2019 18:50:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355627 - head/sys/dev/mmc/host X-SVN-Group: head X-SVN-Commit-Author: manu X-SVN-Commit-Paths: head/sys/dev/mmc/host X-SVN-Commit-Revision: 355627 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Dec 2019 18:50:25 -0000 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 #include #include +#include +#include #include #include @@ -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 #include #include +#include +#include #include 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 #include #include +#include +#include #include 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 #include #include +#include +#include #include 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 #include #include +#include +#include #include 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);