Page MenuHomeFreeBSD

D40717.id.diff
No OneTemporary

D40717.id.diff

Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -1709,6 +1709,7 @@
dev/extres/regulator/regulator.c optional regulator
dev/extres/regulator/regulator_bus.c optional regulator fdt
dev/extres/regulator/regulator_fixed.c optional regulator
+dev/extres/regulator/regulator_pwm.c optional regulator fdt
dev/extres/syscon/syscon.c optional syscon
dev/extres/syscon/syscon_generic.c optional syscon fdt
dev/extres/syscon/syscon_if.m optional syscon
Index: sys/dev/extres/regulator/regulator_pwm.h
===================================================================
--- /dev/null
+++ sys/dev/extres/regulator/regulator_pwm.h
@@ -0,0 +1,43 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Titus Manea <titus@edc.ro>
+ *
+ * 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 ``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 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.
+ */
+
+#ifndef _DEV_EXTRES_REGULATOR_PWM_H_
+#define _DEV_EXTRES_REGULATOR_PWM_H_
+
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/extres/regulator/regulator.h>
+
+struct regnode_pwm_init_def {
+ struct regnode_init_def reg_init_def;
+ bool gpio_open_drain;
+ struct gpiobus_pin *gpio_pin;
+};
+
+int regnode_pwm_register(device_t dev,
+ struct regnode_pwm_init_def *init_def);
+
+#endif /*_DEV_EXTRES_REGULATOR_PWM_H_*/
Index: sys/dev/extres/regulator/regulator_pwm.c
===================================================================
--- /dev/null
+++ sys/dev/extres/regulator/regulator_pwm.c
@@ -0,0 +1,587 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Titus Manea <titus@edc.ro>
+ *
+ * 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 ``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 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 "opt_platform.h"
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include "pwmbus_if.h"
+#endif
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/pwm/pwmbus.h>
+#include <dev/extres/regulator/regulator_pwm.h>
+
+#include "regdev_if.h"
+
+MALLOC_DEFINE(M_PWMREGULATOR, "pwmregulator", "PWM regulator");
+
+/* GPIO list for shared pins. */
+typedef TAILQ_HEAD(gpio_list, gpio_entry) gpio_list_t;
+struct gpio_entry {
+ TAILQ_ENTRY(gpio_entry) link;
+ struct gpiobus_pin gpio_pin;
+ int use_cnt;
+ int enable_cnt;
+ bool always_on;
+};
+static gpio_list_t gpio_list = TAILQ_HEAD_INITIALIZER(gpio_list);
+static struct mtx gpio_list_mtx;
+MTX_SYSINIT(gpio_list_lock, &gpio_list_mtx, "Regulator GPIO lock", MTX_DEF);
+
+struct regnode_pwm_sc {
+ struct regnode_std_param *param;
+ bool gpio_open_drain;
+ struct gpio_entry *gpio_entry;
+};
+
+static int regnode_pwm_init(struct regnode *regnode);
+static int regnode_pwm_enable(struct regnode *regnode, bool enable,
+ int *udelay);
+static int regnode_pwm_status(struct regnode *regnode, int *status);
+static int regnode_pwm_stop(struct regnode *regnode, int *udelay);
+static int regnode_pwm_get_voltage(struct regnode *regnode, int *uvolt);
+static int regnode_pwm_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt,int *udelay);
+
+static regnode_method_t regnode_pwm_methods[] = {
+ /* Regulator interface */
+ REGNODEMETHOD(regnode_init, regnode_pwm_init),
+ REGNODEMETHOD(regnode_enable, regnode_pwm_enable),
+ REGNODEMETHOD(regnode_status, regnode_pwm_status),
+ REGNODEMETHOD(regnode_stop, regnode_pwm_stop),
+ REGNODEMETHOD(regnode_get_voltage, regnode_pwm_get_voltage),
+ REGNODEMETHOD(regnode_set_voltage, regnode_pwm_set_voltage),
+ REGNODEMETHOD(regnode_check_voltage, regnode_method_check_voltage),
+ REGNODEMETHOD_END
+};
+DEFINE_CLASS_1(regnode_pwm, regnode_pwm_class, regnode_pwm_methods,
+ sizeof(struct regnode_pwm_sc), regnode_class);
+
+/*
+ * GPIO list functions.
+ * Two or more regulators can share single GPIO pins, so we must track all
+ * GPIOs in gpio_list.
+ * The GPIO pin is registerd and reseved for first consumer, all others share
+ * gpio_entry with it.
+ */
+static struct gpio_entry *
+regnode_get_gpio_entry(struct gpiobus_pin *gpio_pin)
+{
+ struct gpio_entry *entry, *tmp;
+ device_t busdev;
+ int rv;
+
+ busdev = GPIO_GET_BUS(gpio_pin->dev);
+ if (busdev == NULL)
+ return (NULL);
+ entry = malloc(sizeof(struct gpio_entry), M_PWMREGULATOR,
+ M_WAITOK | M_ZERO);
+
+ mtx_lock(&gpio_list_mtx);
+
+ TAILQ_FOREACH(tmp, &gpio_list, link) {
+ if (tmp->gpio_pin.dev == gpio_pin->dev &&
+ tmp->gpio_pin.pin == gpio_pin->pin) {
+ tmp->use_cnt++;
+ mtx_unlock(&gpio_list_mtx);
+ free(entry, M_PWMREGULATOR);
+ return (tmp);
+ }
+ }
+
+ /* Reserve pin. */
+ /* XXX Can we call gpiobus_acquire_pin() with gpio_list_mtx held? */
+ rv = gpiobus_acquire_pin(busdev, gpio_pin->pin);
+ if (rv != 0) {
+ mtx_unlock(&gpio_list_mtx);
+ free(entry, M_PWMREGULATOR);
+ return (NULL);
+ }
+ /* Everything is OK, build new entry and insert it to list. */
+ entry->gpio_pin = *gpio_pin;
+ entry->use_cnt = 1;
+ TAILQ_INSERT_TAIL(&gpio_list, entry, link);
+
+ mtx_unlock(&gpio_list_mtx);
+ return (entry);
+}
+
+#ifdef FDT
+#include <dev/pwm/ofw_pwm.h>
+struct regpwm_softc
+{
+ device_t dev;
+ bool attach_done;
+ struct regnode_pwm_init_def init_def;
+ phandle_t gpio_prodxref;
+ pcell_t *gpio_cells;
+ int gpio_ncells;
+ struct gpiobus_pin gpio_pin;
+ pwm_channel_t channel;
+ uint32_t sc_dutycycle_unit;
+ uint32_t sc_dutycycle_range[2];
+};
+#endif
+/*
+ * Regulator class implementation.
+ */
+static int
+regnode_pwm_init(struct regnode *regnode)
+{
+ device_t dev;
+ struct regnode_pwm_sc *sc;
+ struct gpiobus_pin *pin;
+ uint32_t flags;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ dev = regnode_get_device(regnode);
+ sc->param = regnode_get_stdparam(regnode);
+ if (sc->gpio_entry == NULL)
+ return (0);
+ pin = &sc->gpio_entry->gpio_pin;
+
+ flags = GPIO_PIN_OUTPUT;
+ if (sc->gpio_open_drain)
+ flags |= GPIO_PIN_OPENDRAIN;
+ if (sc->param->boot_on || sc->param->always_on) {
+ rv = GPIO_PIN_SET(pin->dev, pin->pin, sc->param->enable_active_high);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set GPIO pin: %d\n",
+ pin->pin);
+ return (rv);
+ }
+ }
+
+ rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags);
+ if (rv != 0) {
+ device_printf(dev, "Cannot configure GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+
+ return (0);
+}
+
+/*
+ * Enable/disable regulator.
+ * Take shared GPIO pins in account
+ */
+static int
+regnode_pwm_enable(struct regnode *regnode, bool enable, int *udelay)
+{
+ device_t dev;
+ struct regnode_pwm_sc *sc;
+ struct gpiobus_pin *pin;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ dev = regnode_get_device(regnode);
+
+ *udelay = 0;
+ if (sc->gpio_entry == NULL)
+ return (0);
+ pin = &sc->gpio_entry->gpio_pin;
+ if (enable) {
+ sc->gpio_entry->enable_cnt++;
+ if (sc->gpio_entry->enable_cnt > 1)
+ return (0);
+ } else {
+ KASSERT(sc->gpio_entry->enable_cnt > 0,
+ ("Invalid enable count"));
+ sc->gpio_entry->enable_cnt--;
+ if (sc->gpio_entry->enable_cnt >= 1)
+ return (0);
+ }
+ if (sc->gpio_entry->always_on && !enable)
+ return (0);
+ if (!sc->param->enable_active_high)
+ enable = !enable;
+ rv = GPIO_PIN_SET(pin->dev, pin->pin, enable);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+ *udelay = sc->param->enable_delay;
+ return (0);
+}
+
+/*
+ * Stop (physicaly shutdown) regulator.
+ * Take shared GPIO pins in account
+ */
+static int
+regnode_pwm_stop(struct regnode *regnode, int *udelay)
+{
+ device_t dev;
+ struct regnode_pwm_sc *sc;
+ struct gpiobus_pin *pin;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ dev = regnode_get_device(regnode);
+
+ *udelay = 0;
+ if (sc->gpio_entry == NULL)
+ return (0);
+ if (sc->gpio_entry->always_on)
+ return (0);
+ pin = &sc->gpio_entry->gpio_pin;
+ if (sc->gpio_entry->enable_cnt > 0) {
+ /* Other regulator(s) are enabled. */
+ /* XXXX Any diagnostic message? Or error? */
+ return (0);
+ }
+ rv = GPIO_PIN_SET(pin->dev, pin->pin,
+ sc->param->enable_active_high ? false: true);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+ *udelay = sc->param->enable_delay;
+ return (0);
+}
+
+static int
+regnode_pwm_status(struct regnode *regnode, int *status)
+{
+ struct regnode_pwm_sc *sc;
+ struct gpiobus_pin *pin;
+ uint32_t val;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+
+ *status = 0;
+ if (sc->gpio_entry == NULL) {
+ *status = REGULATOR_STATUS_ENABLED;
+ return (0);
+ }
+ pin = &sc->gpio_entry->gpio_pin;
+
+ rv = GPIO_PIN_GET(pin->dev, pin->pin, &val);
+ if (rv == 0) {
+ if (!sc->param->enable_active_high ^ (val != 0))
+ *status = REGULATOR_STATUS_ENABLED;
+ }
+ return (rv);
+}
+static int
+regnode_pwm_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt, int * udelay)
+{
+ struct regnode_pwm_sc *sc;
+ struct regpwm_softc *dsc;
+ int32_t x0, x1, y0, y1;
+ int32_t x, y;
+ bool enabled;
+
+ sc = regnode_get_softc(regnode);
+ dsc = device_get_softc(regnode_get_device(regnode));
+ PWMBUS_CHANNEL_IS_ENABLED(dsc->channel->dev,dsc->channel->channel, &enabled);
+ if(!enabled)
+ return 0;
+
+ x0 = sc->param->min_uvolt;
+ x1 = sc->param->max_uvolt;
+ y0 = dsc->sc_dutycycle_range[0];
+ y1 = dsc->sc_dutycycle_range[1];
+ x = min_uvolt;
+ y = y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+ dsc->channel->duty = (y * dsc->channel->period) / dsc->sc_dutycycle_unit;
+ PWMBUS_CHANNEL_CONFIG(dsc->channel->dev,dsc->channel->channel,
+ dsc->channel->period, dsc->channel->duty);
+ return 0;
+}
+
+static int
+regnode_pwm_get_voltage(struct regnode *regnode, int *uvolt)
+{
+ struct regnode_pwm_sc *sc;
+ struct regpwm_softc *dsc;
+ int32_t x0, x1, y0, y1;
+ int32_t x, y;
+ bool enabled;
+
+ sc = regnode_get_softc(regnode);
+ dsc = device_get_softc(regnode_get_device(regnode));
+ PWMBUS_CHANNEL_IS_ENABLED(dsc->channel->dev,dsc->channel->channel, &enabled);
+ if(!enabled)
+ return 0;
+
+ PWMBUS_CHANNEL_GET_CONFIG(dsc->channel->dev,dsc->channel->channel,
+ (u_int *) &dsc->channel->period, (u_int *)&dsc->channel->duty);
+
+ x0 = dsc->sc_dutycycle_range[0];
+ x1 = dsc->sc_dutycycle_range[1];
+ y0 = sc->param->min_uvolt;
+ y1 = sc->param->max_uvolt;
+ x = (dsc->channel->duty * dsc->sc_dutycycle_unit) / dsc->channel->period;
+ y = y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+
+ *uvolt = y;
+ return (0);
+}
+
+int
+regnode_pwm_register(device_t dev, struct regnode_pwm_init_def *init_def)
+{
+ struct regnode *regnode;
+ struct regnode_pwm_sc *sc;
+
+ regnode = regnode_create(dev, &regnode_pwm_class,
+ &init_def->reg_init_def);
+ if (regnode == NULL) {
+ device_printf(dev, "Cannot create regulator.\n");
+ return(ENXIO);
+ }
+ sc = regnode_get_softc(regnode);
+ sc->gpio_open_drain = init_def->gpio_open_drain;
+ if (init_def->gpio_pin != NULL) {
+ sc->gpio_entry = regnode_get_gpio_entry(init_def->gpio_pin);
+ if (sc->gpio_entry == NULL)
+ return(ENXIO);
+ }
+ regnode = regnode_register(regnode);
+ if (regnode == NULL) {
+ device_printf(dev, "Cannot register regulator.\n");
+ return(ENXIO);
+ }
+
+ if (sc->gpio_entry != NULL)
+ sc->gpio_entry->always_on |= sc->param->always_on;
+
+ return (0);
+}
+
+/*
+ * OFW Driver implementation.
+ */
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ {"pwm-regulator", 1},
+ {NULL, 0},
+};
+
+static int
+regpwm_get_gpio(struct regpwm_softc * sc)
+{
+ device_t busdev;
+ phandle_t node;
+
+ int rv;
+
+ if (sc->gpio_prodxref == 0)
+ return (0);
+
+ node = ofw_bus_get_node(sc->dev);
+
+ /* Test if controller exist. */
+ sc->gpio_pin.dev = OF_device_from_xref(sc->gpio_prodxref);
+ if (sc->gpio_pin.dev == NULL)
+ return (ENODEV);
+
+ /* Test if GPIO bus already exist. */
+ busdev = GPIO_GET_BUS(sc->gpio_pin.dev);
+ if (busdev == NULL)
+ return (ENODEV);
+
+ rv = gpio_map_gpios(sc->gpio_pin.dev, node,
+ OF_node_from_xref(sc->gpio_prodxref), sc->gpio_ncells,
+ sc->gpio_cells, &(sc->gpio_pin.pin), &(sc->gpio_pin.flags));
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot map the gpio property.\n");
+ return (ENXIO);
+ }
+ sc->init_def.gpio_pin = &sc->gpio_pin;
+ return (0);
+}
+
+static int
+regpwm_parse_fdt(struct regpwm_softc * sc)
+{
+ phandle_t node;
+ int rv;
+ int len;
+ struct regnode_init_def *init_def;
+
+ node = ofw_bus_get_node(sc->dev);
+ init_def = &sc->init_def.reg_init_def;
+
+ rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot parse standard parameters.\n");
+ return(rv);
+ }
+ len = OF_getproplen(node, "pwms");
+ if (len <= 4) {
+ device_printf(sc->dev, ": no pwms property\n");
+ return ENXIO;
+ }
+
+ if (OF_getproplen(node, "voltage-tables") > 0) {
+ device_printf(sc->dev, ": voltage table mode unsupported\n");
+ return ENXIO;
+ }
+
+ if (init_def->std_param.min_uvolt > init_def->std_param.max_uvolt) {
+ device_printf(sc->dev, "min_uvolt > max_uvolt\n");
+ return (ENXIO);
+ }
+ rv = pwm_get_by_ofw_propidx(sc->dev, node, "pwms", 0, &sc->channel);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot map pwm channel %d\n", rv);
+ return (ENXIO);
+ }
+
+ rv = OF_getencprop(node, "pwm-dutycycle-unit", &sc->sc_dutycycle_unit,
+ sizeof(sc->sc_dutycycle_unit));
+ if(rv <= 0) sc->sc_dutycycle_unit = 100;
+ sc->sc_dutycycle_range[0] = 0;
+ sc->sc_dutycycle_range[1] = 100;
+ rv = OF_getencprop(node, "pwm-dutycycle-range",
+ sc->sc_dutycycle_range, sizeof(sc->sc_dutycycle_range));
+// device_printf(sc->dev,"%x %x\n",sc->sc_dutycycle_range[0],sc->sc_dutycycle_range[1]);
+ /* PWM regulator uses 'startup-delay-us' property for enable_delay */
+/*
+ if (!OF_hasprop(node, "gpio"))
+ return (0);
+ rv = ofw_bus_parse_xref_list_alloc(node, "gpio", "#gpio-cells", 0,
+ &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells);
+ if (rv != 0) {
+ sc->gpio_prodxref = 0;
+ device_printf(sc->dev, "Malformed gpio property\n");
+ return (ENXIO);
+ }
+*/
+ return (0);
+}
+
+static void
+regpwm_new_pass(device_t dev)
+{
+ struct regpwm_softc * sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ bus_generic_new_pass(dev);
+
+ if (sc->attach_done)
+ return;
+
+ /* Try to get and configure GPIO. */
+ rv = regpwm_get_gpio(sc);
+ if (rv != 0)
+ return;
+
+ /* Register regulator. */
+ regnode_pwm_register(sc->dev, &sc->init_def);
+ sc->attach_done = true;
+}
+
+static int
+regpwm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "PWM Regulator");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+regpwm_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static int
+regpwm_attach(device_t dev)
+{
+ struct regpwm_softc * sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* Parse FDT data. */
+ rv = regpwm_parse_fdt(sc);
+ if (rv != 0)
+ return(ENXIO);
+
+ /* Fill reset of init. */
+ sc->init_def.reg_init_def.id = 1;
+ sc->init_def.reg_init_def.flags = REGULATOR_FLAGS_STATIC;
+
+ /* Try to get and configure GPIO. */
+ rv = regpwm_get_gpio(sc);
+ if (rv != 0)
+ return (bus_generic_attach(dev));
+
+ /* Register regulator. */
+ regnode_pwm_register(sc->dev, &sc->init_def);
+ sc->attach_done = true;
+
+ return (bus_generic_attach(dev));
+}
+
+static device_method_t regpwm_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, regpwm_probe),
+ DEVMETHOD(device_attach, regpwm_attach),
+ DEVMETHOD(device_detach, regpwm_detach),
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, regpwm_new_pass),
+ /* Regdev interface */
+ DEVMETHOD(regdev_map, regdev_default_ofw_map),
+
+ DEVMETHOD_END
+};
+
+static devclass_t regpwm_devclass;
+DEFINE_CLASS_0(regpwm, regpwm_driver, regpwm_methods,
+ sizeof(struct regpwm_softc));
+EARLY_DRIVER_MODULE(regpwm, simplebus, regpwm_driver,
+ regpwm_devclass, 0, 0, BUS_PASS_BUS);
+
+#endif /* FDT */

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 28, 5:06 PM (21 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28065480
Default Alt Text
D40717.id.diff (18 KB)

Event Timeline