Page MenuHomeFreeBSD

D26874.id54425.diff
No OneTemporary

D26874.id54425.diff

Index: dev/mmc_pwrseq_simple/mmc_pwrseq_simple.c
===================================================================
--- /dev/null
+++ dev/mmc_pwrseq_simple/mmc_pwrseq_simple.c
@@ -0,0 +1,241 @@
+/*-
+ * 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/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmc_fdt_pwrseq.h>
+
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#ifdef EXT_RESOURCES
+#include <dev/extres/clk/clk.h>
+#endif
+
+struct mmc_pwrseq_simple_softc {
+ struct mmc_pwrseq pwrseq; /* Keep first! node, (*f)() */
+ device_t dev;
+ gpio_pin_t reset_pin;
+ clk_t clk;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ { "mmc-pwrseq-simple", 0 },
+
+ { NULL, 0 }
+};
+
+static int
+mmc_pwrseq_simple_off(struct mmc_pwrseq *pwrseq)
+{
+ struct mmc_pwrseq_simple_softc *sc;
+
+ sc = (struct mmc_pwrseq_simple_softc *)pwrseq;
+#ifdef EXT_RESOURCES
+ /* Enable clock. */
+ if (sc->clk != NULL) {
+ int rv;
+
+ rv = clk_disable(sc->clk);
+ if (rv != 0) {
+ device_printf(sc->dev, "Failed to enable 'ext_clock': "
+ "%d\n", rv);
+ return (rv);
+ }
+ }
+#endif
+
+ return (0);
+}
+
+static int
+mmc_pwrseq_simple_up(struct mmc_pwrseq *pwrseq)
+{
+ struct mmc_pwrseq_simple_softc *sc;
+ device_t dev;
+ int rv;
+
+ sc = (struct mmc_pwrseq_simple_softc *)pwrseq;
+ dev = sc->dev;
+
+#ifdef EXT_RESOURCES
+ /* Enable clock. */
+ if (sc->clk != NULL) {
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Failed to enable 'ext_clock': "
+ "%d\n", rv);
+ return (rv);
+ }
+ if (bootverbose) {
+ int64_t freq;
+
+ clk_get_freq(sc->clk, &freq);
+ device_printf(dev, "mmc-pwrseq-simple clock(%s) freq: "
+ "%jd\n", clk_get_name(sc->clk), (intmax_t)freq);
+ }
+ }
+#endif
+
+ /* GPIO/Pin. */
+ rv = gpio_pin_set_active(sc->reset_pin, true);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set 'reset-gpios': %d\n", rv);
+ gpio_pin_release(sc->reset_pin);
+ return (rv);
+ }
+
+ return (0);
+}
+
+static int
+mmc_pwrseq_simple_on(struct mmc_pwrseq *pwrseq)
+{
+ struct mmc_pwrseq_simple_softc *sc;
+ device_t dev;
+ int rv;
+
+ sc = (struct mmc_pwrseq_simple_softc *)pwrseq;
+ dev = sc->dev;
+
+ /* GPIO/Pin. */
+ rv = gpio_pin_set_active(sc->reset_pin, false);
+ if (rv != 0) {
+ device_printf(dev, "Cannot clear 'reset-gpios': %d\n", rv);
+ gpio_pin_release(sc->reset_pin);
+ return (rv);
+ }
+
+ return (0);
+}
+
+static int
+mmc_pwrseq_simple_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_str == NULL)
+ return (ENXIO);
+
+ device_set_desc(dev, "Simple MMC power sequence handler");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+mmc_pwrseq_simple_attach(device_t dev)
+{
+ struct mmc_pwrseq_simple_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->pwrseq.node = ofw_bus_get_node(dev);
+
+ /* Find the 'reset-gpios' pin first. */
+ rv = gpio_pin_get_by_ofw_property(dev, sc->pwrseq.node, "reset-gpios",
+ &sc->reset_pin);
+ if (rv != 0 && rv != ENOENT) {
+ device_printf(dev, "Cannot get 'reset-gpios' gpio: %d\n", rv);
+ return (ENXIO);
+ }
+ if (sc->reset_pin == NULL) {
+ device_printf(dev, "No 'reset-gpios' pin.\n");
+ return (ENXIO);
+ }
+
+#ifdef EXT_RESOURCES
+ /* Find "clocks". */
+ if (clk_get_by_ofw_name(dev, 0, "ext_clock", &sc->clk) != 0) {
+ device_printf(dev, "Could not find clock 'ext_clock'\n");
+ gpio_pin_release(sc->reset_pin);
+ return (ENXIO);
+ }
+#endif
+
+ sc->pwrseq.power_off = mmc_pwrseq_simple_off;
+ sc->pwrseq.power_up = mmc_pwrseq_simple_up;
+ sc->pwrseq.power_on = mmc_pwrseq_simple_on;
+
+ return (mmc_fdt_pwrseq_enqueue(&sc->pwrseq));
+}
+
+static int
+mmc_pwrseq_simple_detach(device_t dev)
+{
+ struct mmc_pwrseq_simple_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = mmc_fdt_pwrseq_dequeue(&sc->pwrseq);
+ /* Do not release resources if dequeu failed; should never happen. */
+ if (error != 0)
+ return (error);
+
+ sc->pwrseq.power_off = NULL;
+ sc->pwrseq.power_up = NULL;
+ sc->pwrseq.power_on = NULL;
+
+ if (sc->reset_pin != NULL)
+ gpio_pin_release(sc->reset_pin);
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+
+ return (0);
+}
+
+static device_method_t mmc_pwrseq_simple_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mmc_pwrseq_simple_probe),
+ DEVMETHOD(device_attach, mmc_pwrseq_simple_attach),
+ DEVMETHOD(device_detach, mmc_pwrseq_simple_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t mmc_pwrseq_simple_driver = {
+ "mmc-pwrseq-simple",
+ mmc_pwrseq_simple_methods,
+ sizeof(struct mmc_pwrseq_simple_softc),
+};
+
+static devclass_t mmc_pwrseq_simple_devclass;
+
+EARLY_DRIVER_MODULE(mmc_pwrseq_simple, ofwbus, mmc_pwrseq_simple_driver,
+ mmc_pwrseq_simple_devclass, NULL, 0, BUS_PASS_TIMER);
+EARLY_DRIVER_MODULE(mmc_pwrseq_simple, simplebus, mmc_pwrseq_simple_driver,
+ mmc_pwrseq_simple_devclass, NULL, 0, BUS_PASS_TIMER);
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2455,6 +2455,7 @@
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/mmc_pwrseq_simple/mmc_pwrseq_simple.c optional mmccam fdt
dev/mmcnull/mmcnull.c optional mmcnull
dev/mn/if_mn.c optional mn pci
dev/mpr/mpr.c optional mpr

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 30, 5:23 PM (44 m, 32 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27389167
Default Alt Text
D26874.id54425.diff (6 KB)

Event Timeline