Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Dec 2019 23:05:20 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r355276 - in head: share/man/man4 sys/dev/gpio
Message-ID:  <201912012305.xB1N5KQq007061@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Dec  1 23:05:20 2019
New Revision: 355276
URL: https://svnweb.freebsd.org/changeset/base/355276

Log:
  Rewrite gpioiic(4) to use the gpio_pin_* API, and to conform to the modern
  FDT bindings document for gpio-i2c devices.
  
  Using the gpio_pin_* functions to acquire/release/manipulate gpio pins
  removes the constraint that both gpio pins must belong to the same gpio
  controller/bank, and that the gpioiic instance must be a child of gpiobus.
  Removing those constraints allows the driver to be fully compatible with
  the modern dts bindings for a gpio bitbanged i2c bus.
  
  For hinted attachment, the two gpio pins still must be on the same gpiobus,
  and the device instance must be a child of that bus.  This preserves
  compatibility for existing installations that have use gpioiic(4) with hints.

Modified:
  head/share/man/man4/gpioiic.4
  head/sys/dev/gpio/gpioiic.c

Modified: head/share/man/man4/gpioiic.4
==============================================================================
--- head/share/man/man4/gpioiic.4	Sun Dec  1 21:29:34 2019	(r355275)
+++ head/share/man/man4/gpioiic.4	Sun Dec  1 23:05:20 2019	(r355276)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 14, 2014
+.Dd December 1, 2019
 .Dt GPIOIIC 4
 .Os
 .Sh NAME
@@ -37,38 +37,42 @@ kernel configuration file:
 .Bd -ragged -offset indent
 .Cd "device gpio"
 .Cd "device gpioiic"
-.Cd "device iic"
 .Cd "device iicbb"
 .Cd "device iicbus"
 .Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+gpioiic_load="YES"
+.Ed
 .Sh DESCRIPTION
 The
 .Nm
 driver provides an IIC bit-banging interface using two GPIO pins for the
-SCL and SDA on the
-.Nm gpiobus .
+SCL and SDA lines on the bus.
+.Pp
 .Nm
-implements an open collector kind of output, as recommended by the standard,
-when driving the pins on the
-.Nm gpiobus ,
-i.e, they are never switched to the logical value of '1',
-or they are '0' or simply open (Hi-Z/tri-state).
-So the pullup resistors are required so
-.Nm
-can work.
+simulates an open collector kind of output when managing the pins on the
+bus, even on systems which don't directly support configuring gpio pins
+in that mode.
+The pins are never driven to the logical value of '1'.
+They are driven to '0' or switched to input mode (Hi-Z/tri-state), and
+an external pullup resistor pulls the line to the 1 state unless some
+other device on the bus is driving it to 0.
 .Pp
+.Sh HINTS CONFIGURATION
 On a
 .Xr device.hints 5
-based system, like
-.Li MIPS ,
-these values are configurable for the
+based system, such as MIPS, these values are configurable for
 .Nm :
 .Bl -tag -width ".Va hint.gpioiic.%d.atXXX"
 .It Va hint.gpioiic.%d.at
 The
 .Nm gpiobus
 you are attaching to.
-Normally just gpiobus0.
+Normally just gpiobus0 on systems with a single bank of gpio pins.
 .It Va hint.gpioiic.%d.pins
 This is a bitmask of the pins on the
 .Nm gpiobus
@@ -78,6 +82,9 @@ To configure pin 0 and 7, use the bitmask of
 0b10000001 and convert it to a hexadecimal value of 0x0081.
 Please note that this mask should only ever have two bits set
 (any other bits - i.e., pins - will be ignored).
+Because
+.Nm
+must be a child of the gpiobus, both gpio pins must be part of that bus.
 .It Va hint.gpioiic.%d.scl
 Indicates which bit in the
 .Va hint.gpioiic.%d.pins
@@ -91,35 +98,32 @@ should be used as the SDATA
 source.
 Optional, defaults to 1.
 .El
-.Pp
-On a
+.Sh FDT CONFIGURATION
+On an
 .Xr FDT 4
-based system, like
-.Li ARM ,
-the DTS part for a
+based system, such as ARM, the DTS node for
 .Nm gpioiic
-device usually looks like:
+conforms to the standard bindings document i2c/i2c-gpio.yaml.
+The device node typically appears at the root of the device tree.
+The following is an example of a
+.Nm
+node with one slave device
+on the IIC bus:
 .Bd -literal
-gpio: gpio {
-
-	gpio-controller;
-	...
-
+/ {
 	gpioiic0 {
-		compatible = "gpioiic";
-		/*
-		 * Attach to GPIO pins 21 and 22.  Set them
-		 * initially as inputs.
-		 */
-		gpios = <&gpio 21 1 0
-			 &gpio 22 1 0>;
-		scl = <0>;		/* GPIO pin 21 - optional */
-		sda = <1>;		/* GPIO pin 22 - optional */
+		compatible = "i2c-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpioiic0>;
+		scl-gpios = <&gpio1  5 GPIO_ACTIVE_HIGH>;
+		sda-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+		status = "okay";
 
-		/* This is an example of a gpioiic child. */
-		gpioiic-child0 {
-			compatible = "lm75";
-			i2c-address = <0x4f>;
+		/* One slave device on the i2c bus. */
+		rtc@51 {
+			compatible="nxp,pcf2127";
+			reg = <0x51>;
+			status = "okay";
 		};
 	};
 };
@@ -128,35 +132,19 @@ gpio: gpio {
 Where:
 .Bl -tag -width ".Va compatible"
 .It Va compatible
-Should always be set to "gpioiic".
-.It Va gpios
-The
-.Va gpios
-property indicates which GPIO pins should be used for SCLOCK and SDATA
-on the GPIO IIC bit-banging bus.
-For more details about the
-.Va gpios
-property, please consult
-.Pa /usr/src/sys/dts/bindings-gpio.txt .
-.It Va scl
-The
-.Va scl
-option indicates which bit in the
-.Va gpios
-should be used as the SCLOCK source.
-Optional, defaults to 0.
-.It Va sda
-The
-.Va sda
-option indicates which bit in the
-.Va gpios
-should be used as the SDATA source.
-Optional, defaults to 1.
+Should be set to "i2c-gpio".
+The deprecated string "gpioiic" is also accepted for backwards compatibility.
+.It Va scl-gpios Va sda-gpios
+These properties indicate which GPIO pins should be used for clock
+and data on the GPIO IIC bit-banging bus.
+There is no requirement that the two pins belong to the same gpio controller.
+.It Va pinctrl-names pinctrl-0
+These properties may be required to configure the chosen pins as gpio
+pins, unless the pins default to that state on your system.
 .El
 .Sh SEE ALSO
 .Xr fdt 4 ,
 .Xr gpio 4 ,
-.Xr gpioled 4 ,
 .Xr iic 4 ,
 .Xr iicbb 4 ,
 .Xr iicbus 4

Modified: head/sys/dev/gpio/gpioiic.c
==============================================================================
--- head/sys/dev/gpio/gpioiic.c	Sun Dec  1 21:29:34 2019	(r355275)
+++ head/sys/dev/gpio/gpioiic.c	Sun Dec  1 23:05:20 2019	(r355276)
@@ -1,9 +1,9 @@
 /*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org>
- * Copyright (c) 2010 Luiz Otavio O Souza
- * All rights reserved.
+ * Copyright (c) 2010 Luiz Otavio O Souza All rights reserved.
+ * Copyright (c) 2019 Ian Lepore <ian@freebsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,14 +39,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/module.h>
 
-#ifdef FDT
-#include <dev/fdt/fdt_common.h>
-#include <dev/ofw/ofw_bus.h>
-#endif
-
 #include <dev/gpio/gpiobusvar.h>
 #include <dev/iicbus/iiconf.h>
-#include <dev/iicbus/iicbus.h>
 
 #include "gpiobus_if.h"
 #include "iicbb_if.h"
@@ -57,200 +51,281 @@ __FBSDID("$FreeBSD$");
 
 struct gpioiic_softc 
 {
-	device_t	sc_dev;
-	device_t	sc_busdev;
-	int		scl_pin;
-	int		sda_pin;
+	device_t	dev;
+	gpio_pin_t	sclpin;
+	gpio_pin_t	sdapin;
 };
 
-static int gpioiic_probe(device_t);
-static int gpioiic_attach(device_t);
+#ifdef FDT
 
-/* iicbb interface */
-static void gpioiic_reset_bus(device_t);
-static void gpioiic_setsda(device_t, int);
-static void gpioiic_setscl(device_t, int);
-static int gpioiic_getsda(device_t);
-static int gpioiic_getscl(device_t);
-static int gpioiic_reset(device_t, u_char, u_char, u_char *);
+#include <dev/ofw/ofw_bus.h>
 
+static struct ofw_compat_data compat_data[] = {
+	{"i2c-gpio",  true}, /* Standard devicetree compat string */
+	{"gpioiic",   true}, /* Deprecated old freebsd compat string */
+	{NULL,        false}
+};
+OFWBUS_PNP_INFO(compat_data);
+SIMPLEBUS_PNP_INFO(compat_data);
+
+static phandle_t
+gpioiic_get_node(device_t bus, device_t dev)
+{
+
+	/* Share our fdt node with iicbus so it can find its child nodes. */
+	return (ofw_bus_get_node(bus));
+}
+
 static int
-gpioiic_probe(device_t dev)
+gpioiic_setup_fdt_pins(struct gpioiic_softc *sc)
 {
-	struct gpiobus_ivar *devi;
+	phandle_t node;
+	int err;
 
-#ifdef FDT
-	if (!ofw_bus_status_okay(dev))
-		return (ENXIO);
-	if (!ofw_bus_is_compatible(dev, "gpioiic"))
-		return (ENXIO);
-#endif
-	devi = GPIOBUS_IVAR(dev);
-	if (devi->npins < GPIOIIC_MIN_PINS) {
-		device_printf(dev,
-		    "gpioiic needs at least %d GPIO pins (only %d given).\n",
-		    GPIOIIC_MIN_PINS, devi->npins);
-		return (ENXIO);
-	}
-	device_set_desc(dev, "GPIO I2C bit-banging driver");
+	node = ofw_bus_get_node(sc->dev);
 
-	return (BUS_PROBE_DEFAULT);
+	/*
+	 * Historically, we used the first two array elements of the gpios
+	 * property.  The modern bindings specify separate scl-gpios and
+	 * sda-gpios properties.  We cope with whichever is present.
+	 */
+	if (OF_hasprop(node, "gpios")) {
+		if ((err = gpio_pin_get_by_ofw_idx(sc->dev, node,
+		    GPIOIIC_SCL_DFLT, &sc->sclpin)) != 0) {
+			device_printf(sc->dev, "invalid gpios property\n");
+			return (err);
+		}
+		if ((err = gpio_pin_get_by_ofw_idx(sc->dev, node,
+		    GPIOIIC_SDA_DFLT, &sc->sdapin)) != 0) {
+			device_printf(sc->dev, "ivalid gpios property\n");
+			return (err);
+		}
+	} else {
+		if ((err = gpio_pin_get_by_ofw_property(sc->dev, node,
+		    "scl-gpios", &sc->sclpin)) != 0) {
+			device_printf(sc->dev, "missing scl-gpios property\n");
+			return (err);
+		}
+		if ((err = gpio_pin_get_by_ofw_property(sc->dev, node,
+		    "sda-gpios", &sc->sdapin)) != 0) {
+			device_printf(sc->dev, "missing sda-gpios property\n");
+			return (err);
+		}
+	}
+	return (0);
 }
+#endif /* FDT */
 
 static int
-gpioiic_attach(device_t dev)
+gpioiic_setup_hinted_pins(struct gpioiic_softc *sc)
 {
-	device_t		bitbang;
-#ifdef FDT
-	phandle_t		node;
-	pcell_t			pin;
-#endif
-	struct gpiobus_ivar	*devi;
-	struct gpioiic_softc	*sc;
+	device_t busdev;
+	const char *busname, *devname;
+	int err, numpins, sclnum, sdanum, unit;
 
-	sc = device_get_softc(dev);
-	sc->sc_dev = dev;
-	sc->sc_busdev = device_get_parent(dev);
-	if (resource_int_value(device_get_name(dev),
-		device_get_unit(dev), "scl", &sc->scl_pin))
-		sc->scl_pin = GPIOIIC_SCL_DFLT;
-	if (resource_int_value(device_get_name(dev),
-		device_get_unit(dev), "sda", &sc->sda_pin))
-		sc->sda_pin = GPIOIIC_SDA_DFLT;
+	devname = device_get_name(sc->dev);
+	unit = device_get_unit(sc->dev);
+	busdev = device_get_parent(sc->dev);
 
+	/*
+	 * If there is not an "at" hint naming our actual parent, then we
+	 * weren't instantiated as a child of gpiobus via hints, and we thus
+	 * can't access ivars that only exist for such children.
+	 */
+	if (resource_string_value(devname, unit, "at", &busname) != 0 ||
+	    (strcmp(busname, device_get_nameunit(busdev)) != 0 &&
+	     strcmp(busname, device_get_name(busdev)) != 0)) {
+		return (ENOENT);
+	}
+
+	/* Make sure there were hints for at least two pins. */
+	numpins = gpiobus_get_npins(sc->dev);
+	if (numpins < GPIOIIC_MIN_PINS) {
 #ifdef FDT
-	if ((node = ofw_bus_get_node(dev)) == -1)
-		return (ENXIO);
-	if (OF_getencprop(node, "scl", &pin, sizeof(pin)) > 0)
-		sc->scl_pin = (int)pin;
-	if (OF_getencprop(node, "sda", &pin, sizeof(pin)) > 0)
-		sc->sda_pin = (int)pin;
+		/*
+		 * Be silent when there are no hints on FDT systems; the FDT
+		 * data will provide the pin config (we'll whine if it doesn't).
+		 */
+		if (numpins == 0) {
+			return (ENOENT);
+		}
 #endif
+		device_printf(sc->dev, 
+		    "invalid pins hint; it must contain at least %d pins\n",
+		    GPIOIIC_MIN_PINS);
+		return (EINVAL);
+	}
 
-	if (sc->scl_pin < 0 || sc->scl_pin > 1)
-		sc->scl_pin = GPIOIIC_SCL_DFLT;
-	if (sc->sda_pin < 0 || sc->sda_pin > 1)
-		sc->sda_pin = GPIOIIC_SDA_DFLT;
+	/*
+	 * Our parent bus has already parsed the pins hint and it will use that
+	 * info when we call gpio_pin_get_by_child_index().  But we have to
+	 * handle the scl/sda index hints that tell us which of the two pins is
+	 * the clock and which is the data.  They're optional, but if present
+	 * they must be a valid index (0 <= index < numpins).
+	 */
+	if ((err = resource_int_value(devname, unit, "scl", &sclnum)) != 0)
+		sclnum = GPIOIIC_SCL_DFLT;
+	else if (sclnum < 0 || sclnum >= numpins) {
+		device_printf(sc->dev, "invalid scl hint %d\n", sclnum);
+		return (EINVAL);
+	}
+	if ((err = resource_int_value(devname, unit, "sda", &sdanum)) != 0)
+		sdanum = GPIOIIC_SDA_DFLT;
+	else if (sdanum < 0 || sdanum >= numpins) {
+		device_printf(sc->dev, "invalid sda hint %d\n", sdanum);
+		return (EINVAL);
+	}
 
-	devi = GPIOBUS_IVAR(dev);
-	device_printf(dev, "SCL pin: %d, SDA pin: %d\n",
-	    devi->pins[sc->scl_pin], devi->pins[sc->sda_pin]);
+	/* Allocate gpiobus_pin structs for the pins we found above. */
+	if ((err = gpio_pin_get_by_child_index(sc->dev, sclnum,
+	    &sc->sclpin)) != 0)
+		return (err);
+	if ((err = gpio_pin_get_by_child_index(sc->dev, sdanum,
+	    &sc->sdapin)) != 0)
+		return (err);
 
-	/* add generic bit-banging code */
-	bitbang = device_add_child(dev, "iicbb", -1);
-	device_probe_and_attach(bitbang);
-
 	return (0);
 }
 
-static int
-gpioiic_detach(device_t dev)
-{
-
-	bus_generic_detach(dev);
-	device_delete_children(dev);
-	return (0);
-}
-
-/*
- * Reset bus by setting SDA first and then SCL. 
- * Must always be called with gpio bus locked.
- */
 static void
-gpioiic_reset_bus(device_t dev)
+gpioiic_setsda(device_t dev, int val)
 {
-	struct gpioiic_softc		*sc = device_get_softc(dev);
+	struct gpioiic_softc *sc = device_get_softc(dev);
+	int err;
 
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
-	    GPIO_PIN_INPUT);
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
-	    GPIO_PIN_INPUT);
+	/*
+	 * Some controllers cannot set an output value while a pin is in input
+	 * mode; in that case we set the pin again after changing mode.
+	 */
+	err = gpio_pin_set_active(sc->sdapin, val);
+	gpio_pin_setflags(sc->sdapin, GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
+	if (err != 0)
+		gpio_pin_set_active(sc->sdapin, val);
 }
 
 static void
-gpioiic_setpin(struct gpioiic_softc *sc, int pin, int val)
+gpioiic_setscl(device_t dev, int val)
 {
-	int				err;
+	struct gpioiic_softc *sc = device_get_softc(dev);
 
-	if (val == 0) {
-		err = GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, pin, 0);
-		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, pin,
-		    GPIO_PIN_OUTPUT);
-
-		/*
-		 * Some controllers cannot set output value while a pin is in
-		 * input mode.
-		 */
-		if (err != 0)
-			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, pin, 0);
-	} else {
-		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, pin,
-		    GPIO_PIN_INPUT);
-	}
+	gpio_pin_setflags(sc->sclpin, GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
+	gpio_pin_set_active(sc->sclpin, val);
 }
 
-static void
-gpioiic_setsda(device_t dev, int val)
+static int
+gpioiic_getscl(device_t dev)
 {
-	struct gpioiic_softc		*sc = device_get_softc(dev);
+	struct gpioiic_softc *sc = device_get_softc(dev);
+	bool val;
 
-	gpioiic_setpin(sc, sc->sda_pin, val);
+	gpio_pin_setflags(sc->sclpin, GPIO_PIN_INPUT);
+	gpio_pin_is_active(sc->sclpin, &val);
+	return (val);
 }
 
-static void
-gpioiic_setscl(device_t dev, int val)
+static int
+gpioiic_getsda(device_t dev)
 {
-	struct gpioiic_softc		*sc = device_get_softc(dev);
+	struct gpioiic_softc *sc = device_get_softc(dev);
+	bool val;
 
-	gpioiic_setpin(sc, sc->scl_pin, val);
+	gpio_pin_setflags(sc->sdapin, GPIO_PIN_INPUT);
+	gpio_pin_is_active(sc->sdapin, &val);
+	return (val);
 }
 
 static int
-gpioiic_getpin(struct gpioiic_softc *sc, int pin)
+gpioiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
 {
-	unsigned int			val;
+	struct gpioiic_softc *sc = device_get_softc(dev);
 
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, pin, GPIO_PIN_INPUT);
-	GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, pin, &val);
-	return ((int)val);
+	/* Stop driving the bus pins. */
+	gpio_pin_setflags(sc->sdapin, GPIO_PIN_INPUT);
+	gpio_pin_setflags(sc->sclpin, GPIO_PIN_INPUT);
+
+	/* Indicate that we have no slave address (master mode). */
+	return (IIC_ENOADDR);
 }
 
-static int
-gpioiic_getscl(device_t dev)
+static void
+gpioiic_cleanup(struct gpioiic_softc *sc)
 {
-	struct gpioiic_softc		*sc = device_get_softc(dev);
 
-	return (gpioiic_getpin(sc, sc->scl_pin));
+	device_delete_children(sc->dev);
+
+	if (sc->sclpin != NULL)
+		gpio_pin_release(sc->sclpin);
+
+	if (sc->sdapin != NULL)
+		gpio_pin_release(sc->sdapin);
 }
 
 static int
-gpioiic_getsda(device_t dev)
+gpioiic_probe(device_t dev)
 {
-	struct gpioiic_softc		*sc = device_get_softc(dev);
+	int rv;
 
-	return (gpioiic_getpin(sc, sc->sda_pin));
+	/*
+	 * By default we only bid to attach if specifically added by our parent
+         * (usually via hint.gpioiic.#.at=busname).  On FDT systems we bid as
+         * the default driver based on being configured in the FDT data.
+	 */
+	rv = BUS_PROBE_NOWILDCARD;
+
+#ifdef FDT
+	if (ofw_bus_status_okay(dev) &&
+	    ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+                rv = BUS_PROBE_DEFAULT;
+#endif
+
+	device_set_desc(dev, "GPIO I2C");
+
+	return (rv);
 }
 
 static int
-gpioiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+gpioiic_attach(device_t dev)
 {
-	struct gpioiic_softc		*sc;
+	struct gpioiic_softc *sc = device_get_softc(dev);
+	int err;
 
-	sc = device_get_softc(dev);
-	gpioiic_reset_bus(sc->sc_dev);
+	sc->dev = dev;
 
-	return (IIC_ENOADDR);
+	/* Acquire our gpio pins. */
+	err = gpioiic_setup_hinted_pins(sc);
+#ifdef FDT
+	if (err != 0)
+		err = gpioiic_setup_fdt_pins(sc);
+#endif
+	if (err != 0) {
+		device_printf(sc->dev, "no pins configured\n");
+		gpioiic_cleanup(sc);
+		return (ENXIO);
+	}
+
+	/* Say what we came up with for pin config. */
+	device_printf(dev, "SCL pin: %s:%d, SDA pin: %s:%d\n",
+	    device_get_nameunit(GPIO_GET_BUS(sc->sclpin->dev)), sc->sclpin->pin,
+	    device_get_nameunit(GPIO_GET_BUS(sc->sdapin->dev)), sc->sdapin->pin);
+
+	/* Add the bitbang driver as our only child; it will add iicbus. */
+	device_add_child(sc->dev, "iicbb", -1);
+	return (bus_generic_attach(dev));
 }
 
-#ifdef FDT
-static phandle_t
-gpioiic_get_node(device_t bus, device_t dev)
+static int
+gpioiic_detach(device_t dev)
 {
+	struct gpioiic_softc *sc = device_get_softc(dev);
+	int err;
 
-	/* We only have one child, the iicbb, which needs our own node. */
-	return (ofw_bus_get_node(bus));
+	if ((err = bus_generic_detach(dev)) != 0)
+		return (err);
+
+	gpioiic_cleanup(sc);
+
+	return (0);
 }
-#endif
 
 static devclass_t gpioiic_devclass;
 
@@ -282,6 +357,7 @@ static driver_t gpioiic_driver = {
 };
 
 DRIVER_MODULE(gpioiic, gpiobus, gpioiic_driver, gpioiic_devclass, 0, 0);
+DRIVER_MODULE(gpioiic, simplebus, gpioiic_driver, gpioiic_devclass, 0, 0);
 DRIVER_MODULE(iicbb, gpioiic, iicbb_driver, iicbb_devclass, 0, 0);
 MODULE_DEPEND(gpioiic, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
 MODULE_DEPEND(gpioiic, gpiobus, 1, 1, 1);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912012305.xB1N5KQq007061>