Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F96525613
D26872.id78473.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D26872.id78473.diff
View Options
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2454,6 +2454,7 @@
dev/mmc/mmcbus_if.m standard
dev/mmc/mmcsd.c optional mmcsd !mmccam
dev/mmc/mmc_fdt_helpers.c optional mmc fdt | mmccam fdt
+dev/mmc/mmc_fdt_pwrseq.c optional mmc fdt | mmccam fdt
dev/mmcnull/mmcnull.c optional mmcnull
dev/mn/if_mn.c optional mn pci
dev/mpr/mpr.c optional mpr
Index: sys/dev/mmc/host/dwmmc.c
===================================================================
--- sys/dev/mmc/host/dwmmc.c
+++ sys/dev/mmc/host/dwmmc.c
@@ -51,6 +51,7 @@
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcbrvar.h>
#include <dev/mmc/mmc_fdt_helpers.h>
+#include <dev/mmc/mmc_fdt_pwrseq.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
@@ -832,6 +833,8 @@
device_printf(sc->dev, "Cannot disable vqmmc regulator\n");
#endif
+ mmc_fdt_free(&sc->mmc_helper);
+
return (0);
}
@@ -933,6 +936,23 @@
return (ret);
}
+static void
+dwmmc_update_power_mode(struct dwmmc_softc *sc, enum mmc_power_mode power_mode)
+{
+
+ switch (power_mode) {
+ case power_off:
+ mmc_fdt_pwrseq_off(&sc->mmc_helper);
+ break;
+ case power_up:
+ mmc_fdt_pwrseq_up(&sc->mmc_helper);
+ break;
+ case power_on:
+ mmc_fdt_pwrseq_on(&sc->mmc_helper);
+ break;
+ };
+}
+
static int
dma_done(struct dwmmc_softc *sc, struct mmc_command *cmd)
{
@@ -1581,6 +1601,7 @@
ios->power_mode = new_ios->power_mode;
if (bootverbose)
device_printf(sc->dev, "Power mode => %d\n", ios->power_mode);
+ dwmmc_update_power_mode(sc, ios->power_mode);
}
if (cts->ios_valid & MMC_BT) {
ios->timing = new_ios->timing;
Index: sys/dev/mmc/mmc_fdt_helpers.h
===================================================================
--- sys/dev/mmc/mmc_fdt_helpers.h
+++ sys/dev/mmc/mmc_fdt_helpers.h
@@ -33,6 +33,8 @@
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/mmc/mmc_fdt_pwrseq.h>
+
#ifdef EXT_RESOURCES
#include <dev/extres/regulator/regulator.h>
#endif
@@ -58,7 +60,8 @@
#define MMC_PROP_NO_SDIO (1 << 5)
#define MMC_PROP_NO_SD (1 << 6)
#define MMC_PROP_NO_MMC (1 << 7)
-
+#define MMC_PROP_SDIO_IRQ (1 << 8)
+ struct mmc_pwrseq *pwrseq;
#ifdef EXT_RESOURCES
regulator_t vmmc_supply;
regulator_t vqmmc_supply;
@@ -68,6 +71,8 @@
typedef void (*mmc_fdt_cd_handler)(device_t dev, bool present);
int mmc_fdt_parse(device_t dev, phandle_t node, struct mmc_fdt_helper *helper, struct mmc_host *host);
+void mmc_fdt_free(struct mmc_fdt_helper *);
+
int mmc_fdt_gpio_setup(device_t dev, phandle_t node, struct mmc_fdt_helper *helper, mmc_fdt_cd_handler handler);
void mmc_fdt_gpio_teardown(struct mmc_fdt_helper *helper);
bool mmc_fdt_gpio_get_present(struct mmc_fdt_helper *helper);
Index: sys/dev/mmc/mmc_fdt_helpers.c
===================================================================
--- sys/dev/mmc/mmc_fdt_helpers.c
+++ sys/dev/mmc/mmc_fdt_helpers.c
@@ -135,6 +135,8 @@
helper->props |= MMC_PROP_NO_SD;
if (OF_hasprop(node, "no-mmc"))
helper->props |= MMC_PROP_NO_MMC;
+ if (OF_hasprop(node, "cap-sdio-irq"))
+ helper->props |= MMC_PROP_SDIO_IRQ;
if (!(helper->props & MMC_PROP_NO_SD))
mmc_fdt_parse_sd_speed(node, host);
@@ -181,9 +183,25 @@
host->caps |= MMC_CAP_SIGNALING_330;
#endif
+ (void) mmc_fdt_parse_pwrseq(dev, node, helper, host);
+
return (0);
}
+void
+mmc_fdt_free(struct mmc_fdt_helper *helper)
+{
+
+ if (helper == NULL)
+ return;
+
+ mmc_fdt_free_pwrseq(helper);
+ mmc_fdt_gpio_teardown(helper);
+#ifdef EXT_RESOURCES
+ /* Cleanup regulators. */
+#endif
+}
+
/*
* Card detect interrupt handler.
*/
Index: sys/dev/mmc/mmc_fdt_pwrseq.h
===================================================================
--- /dev/null
+++ sys/dev/mmc/mmc_fdt_pwrseq.h
@@ -0,0 +1,55 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Bjoern A. Zeeb
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_MMC_MMC_FDT_PWRSEQ_H
+#define _DEV_MMC_MMC_FDT_PWRSEQ_H
+
+#include <dev/ofw/ofw_bus.h>
+
+struct mmc_pwrseq {
+ phandle_t node;
+ int (*power_off)(struct mmc_pwrseq *);
+ int (*power_up)(struct mmc_pwrseq *);
+ int (*power_on)(struct mmc_pwrseq *);
+ TAILQ_ENTRY(mmc_pwrseq) mmc_pwrseq_elm;
+};
+
+struct mmc_fdt_helper;
+int mmc_fdt_parse_pwrseq(device_t, phandle_t, struct mmc_fdt_helper *,
+ struct mmc_host *);
+void mmc_fdt_free_pwrseq(struct mmc_fdt_helper *);
+
+int mmc_fdt_pwrseq_enqueue(struct mmc_pwrseq *);
+int mmc_fdt_pwrseq_dequeue(struct mmc_pwrseq *);
+
+int mmc_fdt_pwrseq_off(struct mmc_fdt_helper *);
+int mmc_fdt_pwrseq_up(struct mmc_fdt_helper *);
+int mmc_fdt_pwrseq_on(struct mmc_fdt_helper *);
+
+#endif /* _DEV_MMC_MMC_FDT_PWRSEQ_H */
Index: sys/dev/mmc/mmc_fdt_pwrseq.c
===================================================================
--- /dev/null
+++ sys/dev/mmc/mmc_fdt_pwrseq.c
@@ -0,0 +1,181 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Bjoern A. Zeeb
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/gpio.h>
+#include <sys/taskqueue.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmc_fdt_helpers.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+
+/*
+ * I was wondering how the "power sequence" would call things in sequence
+ * and realised that turning pins on/off needs to happen at different times
+ * so it is not really a sequence but a collection of a few helper function
+ * calls which are always present in the mmc (or rather driver) code.
+ * Given most people have never had a need for the mmc-pwrseq-simple calls
+ * try to make NOPs by default. That's where my hackery ends and I have to
+ * write proper code.
+ */
+
+static TAILQ_HEAD(mmc_pwqseq_head, mmc_pwrseq) mmc_pwqseq_q =
+ TAILQ_HEAD_INITIALIZER(mmc_pwqseq_q);
+
+#define PWRSEQ_LOCK()
+#define PWRSEQ_UNLOCK()
+
+int
+mmc_fdt_parse_pwrseq(device_t dev, phandle_t node,
+ struct mmc_fdt_helper *helper, struct mmc_host *host)
+{
+ phandle_t xref_pwrseq, node_pwrseq;
+ struct mmc_pwrseq *pwrseq;
+ int rv;
+
+ rv = OF_getencprop(node, "mmc-pwrseq", &xref_pwrseq,
+ sizeof(xref_pwrseq));
+ if (rv < 0) {
+ if (bootverbose)
+ device_printf(dev, "No mmc-pwrseq xref: %d.\n", rv);
+ return (ENXIO);
+ }
+
+ /*
+ * XXX-BZ this is a bit unelegant, but I am not sure how to do OF/dev
+ * chains and attach the specific pwrseq implementation as a child.
+ * I wonder if we could do this more newbus like calling
+ * device_probe_attach_child() somehow. Anyway, first proof of concept.
+ */
+ node_pwrseq = OF_node_from_xref(xref_pwrseq);
+ if (node_pwrseq == xref_pwrseq) {
+ device_printf(dev, "Cannot find xref for 'mmc-pwrseq' entry\n");
+ return (ENXIO);
+ }
+
+ PWRSEQ_LOCK();
+ TAILQ_FOREACH(pwrseq, &mmc_pwqseq_q, mmc_pwrseq_elm) {
+ if (pwrseq->node == node_pwrseq) {
+ helper->pwrseq = pwrseq;
+ device_printf(dev, "Found mmc-pwrseq handler.\n");
+ break;
+ }
+ }
+ PWRSEQ_UNLOCK();
+
+ return (ENXIO);
+}
+
+void
+mmc_fdt_free_pwrseq(struct mmc_fdt_helper *helper)
+{
+
+ if (helper == NULL)
+ return;
+
+ /* XXX for now just nuke the pointer as we don't do newbus or refcnt. */
+ if (helper->pwrseq != NULL)
+ helper->pwrseq = NULL;
+}
+
+/* -------------------------------------------------------------------------- */
+
+int
+mmc_fdt_pwrseq_enqueue(struct mmc_pwrseq *pwrseq)
+{
+
+ KASSERT(pwrseq != NULL, ("%s: pwrseq is NULL\n", __func__));
+
+ PWRSEQ_LOCK();
+ TAILQ_INSERT_TAIL(&mmc_pwqseq_q, pwrseq, mmc_pwrseq_elm);
+ PWRSEQ_UNLOCK();
+
+ return (0);
+}
+
+int
+mmc_fdt_pwrseq_dequeue(struct mmc_pwrseq *pwrseq)
+{
+
+ KASSERT(pwrseq != NULL, ("%s: pwrseq is NULL\n", __func__));
+
+ PWRSEQ_LOCK();
+ TAILQ_REMOVE(&mmc_pwqseq_q, pwrseq, mmc_pwrseq_elm);
+ PWRSEQ_UNLOCK();
+
+ return (0);
+}
+
+/* -------------------------------------------------------------------------- */
+
+int
+mmc_fdt_pwrseq_off(struct mmc_fdt_helper *helper)
+{
+
+ if (helper == NULL || helper->pwrseq == NULL)
+ return (0);
+
+ if (helper->pwrseq->power_off == NULL)
+ return (0);
+
+ return (helper->pwrseq->power_off(helper->pwrseq));
+}
+
+int
+mmc_fdt_pwrseq_up(struct mmc_fdt_helper *helper)
+{
+
+ if (helper == NULL || helper->pwrseq == NULL)
+ return (0);
+
+ if (helper->pwrseq->power_up == NULL)
+ return (0);
+
+ return (helper->pwrseq->power_up(helper->pwrseq));
+}
+
+int
+mmc_fdt_pwrseq_on(struct mmc_fdt_helper *helper)
+{
+
+ if (helper == NULL || helper->pwrseq == NULL)
+ return (0);
+
+ if (helper->pwrseq->power_on == NULL)
+ return (0);
+
+ return (helper->pwrseq->power_on(helper->pwrseq));
+}
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Sep 26, 8:44 AM (19 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12820834
Default Alt Text
D26872.id78473.diff (11 KB)
Attached To
Mode
D26872: mmc: implement mmc-pwrseq
Attached
Detach File
Event Timeline
Log In to Comment