xref: /freebsd/sys/compat/linuxkpi/common/src/linux_i2cbb.c (revision 6364180582b769b8fb8fba83511748af3b2c9efd)
11961a14aSEmmanuel Vadot /*-
21961a14aSEmmanuel Vadot  * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG
31961a14aSEmmanuel Vadot  *
41961a14aSEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
51961a14aSEmmanuel Vadot  * modification, are permitted provided that the following conditions
61961a14aSEmmanuel Vadot  * are met:
71961a14aSEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
81961a14aSEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
91961a14aSEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
101961a14aSEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
111961a14aSEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
121961a14aSEmmanuel Vadot  *
131961a14aSEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
141961a14aSEmmanuel Vadot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151961a14aSEmmanuel Vadot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
161961a14aSEmmanuel Vadot  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
171961a14aSEmmanuel Vadot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
181961a14aSEmmanuel Vadot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
191961a14aSEmmanuel Vadot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201961a14aSEmmanuel Vadot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
211961a14aSEmmanuel Vadot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
221961a14aSEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
231961a14aSEmmanuel Vadot  * SUCH DAMAGE.
241961a14aSEmmanuel Vadot  *
251961a14aSEmmanuel Vadot  */
261961a14aSEmmanuel Vadot 
271961a14aSEmmanuel Vadot #include <sys/cdefs.h>
281961a14aSEmmanuel Vadot __FBSDID("$FreeBSD$");
291961a14aSEmmanuel Vadot 
301961a14aSEmmanuel Vadot #include <sys/param.h>
311961a14aSEmmanuel Vadot #include <sys/systm.h>
321961a14aSEmmanuel Vadot #include <sys/bus.h>
331961a14aSEmmanuel Vadot #include <sys/malloc.h>
341961a14aSEmmanuel Vadot 
351961a14aSEmmanuel Vadot #include <dev/iicbus/iicbus.h>
361961a14aSEmmanuel Vadot #include <dev/iicbus/iiconf.h>
371961a14aSEmmanuel Vadot 
381961a14aSEmmanuel Vadot #include <linux/device.h>
391961a14aSEmmanuel Vadot #include <linux/i2c.h>
401961a14aSEmmanuel Vadot #include <linux/i2c-algo-bit.h>
411961a14aSEmmanuel Vadot #include <linux/list.h>
421961a14aSEmmanuel Vadot #include <linux/pci.h>
431961a14aSEmmanuel Vadot 
44*63641805SEmmanuel Vadot #include "iicbus_if.h"
451961a14aSEmmanuel Vadot #include "iicbb_if.h"
461961a14aSEmmanuel Vadot #include "lkpi_iic_if.h"
471961a14aSEmmanuel Vadot 
481961a14aSEmmanuel Vadot static void lkpi_iicbb_setsda(device_t dev, int val);
491961a14aSEmmanuel Vadot static void lkpi_iicbb_setscl(device_t dev, int val);
501961a14aSEmmanuel Vadot static int lkpi_iicbb_getscl(device_t dev);
511961a14aSEmmanuel Vadot static int lkpi_iicbb_getsda(device_t dev);
521961a14aSEmmanuel Vadot static int lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
53*63641805SEmmanuel Vadot static int lkpi_iicbb_pre_xfer(device_t dev);
54*63641805SEmmanuel Vadot static void lkpi_iicbb_post_xfer(device_t dev);
551961a14aSEmmanuel Vadot 
561961a14aSEmmanuel Vadot struct lkpi_iicbb_softc {
571961a14aSEmmanuel Vadot 	device_t		iicbb;
581961a14aSEmmanuel Vadot 	struct i2c_adapter	*adapter;
591961a14aSEmmanuel Vadot };
601961a14aSEmmanuel Vadot 
61*63641805SEmmanuel Vadot static struct sx lkpi_sx_i2cbb;
62*63641805SEmmanuel Vadot 
63*63641805SEmmanuel Vadot static void
64*63641805SEmmanuel Vadot lkpi_sysinit_i2cbb(void *arg __unused)
65*63641805SEmmanuel Vadot {
66*63641805SEmmanuel Vadot 
67*63641805SEmmanuel Vadot 	sx_init(&lkpi_sx_i2cbb, "lkpi-i2cbb");
68*63641805SEmmanuel Vadot }
69*63641805SEmmanuel Vadot 
70*63641805SEmmanuel Vadot static void
71*63641805SEmmanuel Vadot lkpi_sysuninit_i2cbb(void *arg __unused)
72*63641805SEmmanuel Vadot {
73*63641805SEmmanuel Vadot 
74*63641805SEmmanuel Vadot 	sx_destroy(&lkpi_sx_i2cbb);
75*63641805SEmmanuel Vadot }
76*63641805SEmmanuel Vadot 
77*63641805SEmmanuel Vadot SYSINIT(lkpi_i2cbb, SI_SUB_DRIVERS, SI_ORDER_ANY,
78*63641805SEmmanuel Vadot     lkpi_sysinit_i2cbb, NULL);
79*63641805SEmmanuel Vadot SYSUNINIT(lkpi_i2cbb, SI_SUB_DRIVERS, SI_ORDER_ANY,
80*63641805SEmmanuel Vadot     lkpi_sysuninit_i2cbb, NULL);
81*63641805SEmmanuel Vadot 
821961a14aSEmmanuel Vadot static int
831961a14aSEmmanuel Vadot lkpi_iicbb_probe(device_t dev)
841961a14aSEmmanuel Vadot {
851961a14aSEmmanuel Vadot 
861961a14aSEmmanuel Vadot 	device_set_desc(dev, "LinuxKPI I2CBB");
871961a14aSEmmanuel Vadot 	return (BUS_PROBE_NOWILDCARD);
881961a14aSEmmanuel Vadot }
891961a14aSEmmanuel Vadot 
901961a14aSEmmanuel Vadot static int
911961a14aSEmmanuel Vadot lkpi_iicbb_attach(device_t dev)
921961a14aSEmmanuel Vadot {
931961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
941961a14aSEmmanuel Vadot 
951961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
961961a14aSEmmanuel Vadot 	sc->iicbb = device_add_child(dev, "iicbb", -1);
971961a14aSEmmanuel Vadot 	if (sc->iicbb == NULL) {
981961a14aSEmmanuel Vadot 		device_printf(dev, "Couldn't add iicbb child, aborting\n");
991961a14aSEmmanuel Vadot 		return (ENXIO);
1001961a14aSEmmanuel Vadot 	}
1011961a14aSEmmanuel Vadot 	bus_generic_attach(dev);
1021961a14aSEmmanuel Vadot 	return (0);
1031961a14aSEmmanuel Vadot }
1041961a14aSEmmanuel Vadot 
1051961a14aSEmmanuel Vadot static int
1061961a14aSEmmanuel Vadot lkpi_iicbb_detach(device_t dev)
1071961a14aSEmmanuel Vadot {
1081961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1091961a14aSEmmanuel Vadot 
1101961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1111961a14aSEmmanuel Vadot 	if (sc->iicbb)
1121961a14aSEmmanuel Vadot 		device_delete_child(dev, sc->iicbb);
1131961a14aSEmmanuel Vadot 	return (0);
1141961a14aSEmmanuel Vadot }
1151961a14aSEmmanuel Vadot 
1161961a14aSEmmanuel Vadot static int
1171961a14aSEmmanuel Vadot lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter)
1181961a14aSEmmanuel Vadot {
1191961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
120*63641805SEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1211961a14aSEmmanuel Vadot 
1221961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1231961a14aSEmmanuel Vadot 	sc->adapter = adapter;
1241961a14aSEmmanuel Vadot 
125*63641805SEmmanuel Vadot 	/*
126*63641805SEmmanuel Vadot 	 * Set iicbb timing parameters deriving speed from the protocol delay.
127*63641805SEmmanuel Vadot 	 */
128*63641805SEmmanuel Vadot 	algo_data = adapter->algo_data;
129*63641805SEmmanuel Vadot 	if (algo_data->udelay != 0)
130*63641805SEmmanuel Vadot 		IICBUS_RESET(sc->iicbb, 1000000 / algo_data->udelay, 0, NULL);
1311961a14aSEmmanuel Vadot 	return (0);
1321961a14aSEmmanuel Vadot }
1331961a14aSEmmanuel Vadot 
13425d21a84SEmmanuel Vadot static struct i2c_adapter *
13525d21a84SEmmanuel Vadot lkpi_iicbb_get_adapter(device_t dev)
13625d21a84SEmmanuel Vadot {
13725d21a84SEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
13825d21a84SEmmanuel Vadot 
13925d21a84SEmmanuel Vadot 	sc = device_get_softc(dev);
14025d21a84SEmmanuel Vadot 	return (sc->adapter);
14125d21a84SEmmanuel Vadot }
14225d21a84SEmmanuel Vadot 
1431961a14aSEmmanuel Vadot static device_method_t lkpi_iicbb_methods[] = {
1441961a14aSEmmanuel Vadot 	/* device interface */
1451961a14aSEmmanuel Vadot 	DEVMETHOD(device_probe,		lkpi_iicbb_probe),
1461961a14aSEmmanuel Vadot 	DEVMETHOD(device_attach,	lkpi_iicbb_attach),
1471961a14aSEmmanuel Vadot 	DEVMETHOD(device_detach,	lkpi_iicbb_detach),
1481961a14aSEmmanuel Vadot 	DEVMETHOD(device_suspend,	bus_generic_suspend),
1491961a14aSEmmanuel Vadot 	DEVMETHOD(device_resume,	bus_generic_resume),
1501961a14aSEmmanuel Vadot 
1511961a14aSEmmanuel Vadot 	/* iicbb interface */
1521961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setsda,		lkpi_iicbb_setsda),
1531961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setscl,		lkpi_iicbb_setscl),
1541961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getsda,		lkpi_iicbb_getsda),
1551961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getscl,		lkpi_iicbb_getscl),
1561961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_reset,		lkpi_iicbb_reset),
157*63641805SEmmanuel Vadot 	DEVMETHOD(iicbb_pre_xfer,	lkpi_iicbb_pre_xfer),
158*63641805SEmmanuel Vadot 	DEVMETHOD(iicbb_post_xfer,	lkpi_iicbb_post_xfer),
1591961a14aSEmmanuel Vadot 
1601961a14aSEmmanuel Vadot 	/* lkpi_iicbb interface */
1611961a14aSEmmanuel Vadot 	DEVMETHOD(lkpi_iic_add_adapter,	lkpi_iicbb_add_adapter),
16225d21a84SEmmanuel Vadot 	DEVMETHOD(lkpi_iic_get_adapter,	lkpi_iicbb_get_adapter),
1631961a14aSEmmanuel Vadot 
1641961a14aSEmmanuel Vadot 	DEVMETHOD_END
1651961a14aSEmmanuel Vadot };
1661961a14aSEmmanuel Vadot 
1671961a14aSEmmanuel Vadot driver_t lkpi_iicbb_driver = {
1681961a14aSEmmanuel Vadot 	"lkpi_iicbb",
1691961a14aSEmmanuel Vadot 	lkpi_iicbb_methods,
1701961a14aSEmmanuel Vadot 	sizeof(struct lkpi_iicbb_softc),
1711961a14aSEmmanuel Vadot };
1721961a14aSEmmanuel Vadot 
173*63641805SEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, drmn, lkpi_iicbb_driver, 0, 0);
174*63641805SEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, drm, lkpi_iicbb_driver, 0, 0);
1758c13dd83SJohn Baldwin DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, 0, 0);
176*63641805SEmmanuel Vadot MODULE_DEPEND(linuxkpi, iicbb, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1771961a14aSEmmanuel Vadot 
1781961a14aSEmmanuel Vadot static void
1791961a14aSEmmanuel Vadot lkpi_iicbb_setsda(device_t dev, int val)
1801961a14aSEmmanuel Vadot {
1811961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1821961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1831961a14aSEmmanuel Vadot 
1841961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
185*63641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
1861961a14aSEmmanuel Vadot 	algo_data->setsda(algo_data->data, val);
1871961a14aSEmmanuel Vadot }
1881961a14aSEmmanuel Vadot 
1891961a14aSEmmanuel Vadot static void
1901961a14aSEmmanuel Vadot lkpi_iicbb_setscl(device_t dev, int val)
1911961a14aSEmmanuel Vadot {
1921961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1931961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1941961a14aSEmmanuel Vadot 
1951961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
196*63641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
1971961a14aSEmmanuel Vadot 	algo_data->setscl(algo_data->data, val);
1981961a14aSEmmanuel Vadot }
1991961a14aSEmmanuel Vadot 
2001961a14aSEmmanuel Vadot static int
2011961a14aSEmmanuel Vadot lkpi_iicbb_getscl(device_t dev)
2021961a14aSEmmanuel Vadot {
2031961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
2041961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
205*63641805SEmmanuel Vadot 	int ret;
2061961a14aSEmmanuel Vadot 
2071961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
208*63641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
2091961a14aSEmmanuel Vadot 	ret = algo_data->getscl(algo_data->data);
2101961a14aSEmmanuel Vadot 	return (ret);
2111961a14aSEmmanuel Vadot }
2121961a14aSEmmanuel Vadot 
2131961a14aSEmmanuel Vadot static int
2141961a14aSEmmanuel Vadot lkpi_iicbb_getsda(device_t dev)
2151961a14aSEmmanuel Vadot {
2161961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
2171961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
218*63641805SEmmanuel Vadot 	int ret;
2191961a14aSEmmanuel Vadot 
2201961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
221*63641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
2221961a14aSEmmanuel Vadot 	ret = algo_data->getsda(algo_data->data);
2231961a14aSEmmanuel Vadot 	return (ret);
2241961a14aSEmmanuel Vadot }
2251961a14aSEmmanuel Vadot 
2261961a14aSEmmanuel Vadot static int
2271961a14aSEmmanuel Vadot lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
2281961a14aSEmmanuel Vadot {
2291961a14aSEmmanuel Vadot 
230*63641805SEmmanuel Vadot 	/* That doesn't seems to be supported in linux */
2311961a14aSEmmanuel Vadot 	return (0);
2321961a14aSEmmanuel Vadot }
2331961a14aSEmmanuel Vadot 
234*63641805SEmmanuel Vadot static int
235*63641805SEmmanuel Vadot lkpi_iicbb_pre_xfer(device_t dev)
2361961a14aSEmmanuel Vadot {
237*63641805SEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
238*63641805SEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
239*63641805SEmmanuel Vadot 	int rc = 0;
2401961a14aSEmmanuel Vadot 
241*63641805SEmmanuel Vadot 	sc = device_get_softc(dev);
242*63641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
243*63641805SEmmanuel Vadot 	if (algo_data->pre_xfer != 0)
244*63641805SEmmanuel Vadot 		rc = algo_data->pre_xfer(sc->adapter);
245*63641805SEmmanuel Vadot 	return (rc);
246*63641805SEmmanuel Vadot }
247*63641805SEmmanuel Vadot 
248*63641805SEmmanuel Vadot static void
249*63641805SEmmanuel Vadot lkpi_iicbb_post_xfer(device_t dev)
250*63641805SEmmanuel Vadot {
251*63641805SEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
252*63641805SEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
253*63641805SEmmanuel Vadot 
254*63641805SEmmanuel Vadot 	sc = device_get_softc(dev);
255*63641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
256*63641805SEmmanuel Vadot 	if (algo_data->post_xfer != NULL)
257*63641805SEmmanuel Vadot 		algo_data->post_xfer(sc->adapter);
258*63641805SEmmanuel Vadot }
259*63641805SEmmanuel Vadot 
260*63641805SEmmanuel Vadot int
261*63641805SEmmanuel Vadot lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
262*63641805SEmmanuel Vadot     int nmsgs)
263*63641805SEmmanuel Vadot {
264*63641805SEmmanuel Vadot 	struct iic_msg *bsd_msgs;
265*63641805SEmmanuel Vadot 	int ret = ENXIO;
266*63641805SEmmanuel Vadot 
267*63641805SEmmanuel Vadot 	linux_set_current(curthread);
268*63641805SEmmanuel Vadot 
269*63641805SEmmanuel Vadot 	bsd_msgs = malloc(sizeof(struct iic_msg) * nmsgs,
270*63641805SEmmanuel Vadot 	    M_DEVBUF, M_WAITOK | M_ZERO);
271*63641805SEmmanuel Vadot 
272*63641805SEmmanuel Vadot 	for (int i = 0; i < nmsgs; i++) {
273*63641805SEmmanuel Vadot 		bsd_msgs[i].slave = msgs[i].addr << 1;
274*63641805SEmmanuel Vadot 		bsd_msgs[i].len = msgs[i].len;
275*63641805SEmmanuel Vadot 		bsd_msgs[i].buf = msgs[i].buf;
276*63641805SEmmanuel Vadot 		if (msgs[i].flags & I2C_M_RD)
277*63641805SEmmanuel Vadot 			bsd_msgs[i].flags |= IIC_M_RD;
278*63641805SEmmanuel Vadot 		if (msgs[i].flags & I2C_M_NOSTART)
279*63641805SEmmanuel Vadot 			bsd_msgs[i].flags |= IIC_M_NOSTART;
280*63641805SEmmanuel Vadot 	}
281*63641805SEmmanuel Vadot 
282*63641805SEmmanuel Vadot 	for (int unit = 0; ; unit++) {
283*63641805SEmmanuel Vadot 		device_t child;
284*63641805SEmmanuel Vadot 		struct lkpi_iicbb_softc *sc;
285*63641805SEmmanuel Vadot 
286*63641805SEmmanuel Vadot 		child = device_find_child(adapter->dev.parent->bsddev,
287*63641805SEmmanuel Vadot 		    "lkpi_iicbb", unit);
288*63641805SEmmanuel Vadot 		if (child == NULL)
289*63641805SEmmanuel Vadot 			break;
290*63641805SEmmanuel Vadot 		if (adapter == LKPI_IIC_GET_ADAPTER(child)) {
291*63641805SEmmanuel Vadot 			sc = device_get_softc(child);
292*63641805SEmmanuel Vadot 			ret = IICBUS_TRANSFER(sc->iicbb, bsd_msgs, nmsgs);
293*63641805SEmmanuel Vadot 			ret = iic2errno(ret);
294*63641805SEmmanuel Vadot 			break;
295*63641805SEmmanuel Vadot 		}
296*63641805SEmmanuel Vadot 	}
297*63641805SEmmanuel Vadot 
298*63641805SEmmanuel Vadot 	free(bsd_msgs, M_DEVBUF);
299*63641805SEmmanuel Vadot 
300*63641805SEmmanuel Vadot 	if (ret != 0)
301*63641805SEmmanuel Vadot 		return (-ret);
302*63641805SEmmanuel Vadot 	return (nmsgs);
3031961a14aSEmmanuel Vadot }
3041961a14aSEmmanuel Vadot 
3051961a14aSEmmanuel Vadot int
3061961a14aSEmmanuel Vadot lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter)
3071961a14aSEmmanuel Vadot {
3081961a14aSEmmanuel Vadot 	device_t lkpi_iicbb;
3091961a14aSEmmanuel Vadot 	int error;
3101961a14aSEmmanuel Vadot 
3111961a14aSEmmanuel Vadot 	if (bootverbose)
3121961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
3131961a14aSEmmanuel Vadot 		    "Adding i2c adapter %s\n", adapter->name);
314*63641805SEmmanuel Vadot 	sx_xlock(&lkpi_sx_i2cbb);
3151961a14aSEmmanuel Vadot 	lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1);
3161961a14aSEmmanuel Vadot 	if (lkpi_iicbb == NULL) {
3171961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n");
318*63641805SEmmanuel Vadot 		sx_xunlock(&lkpi_sx_i2cbb);
3191961a14aSEmmanuel Vadot 		return (ENXIO);
3201961a14aSEmmanuel Vadot 	}
3211961a14aSEmmanuel Vadot 
322*63641805SEmmanuel Vadot 	bus_topo_lock();
3231961a14aSEmmanuel Vadot 	error = bus_generic_attach(adapter->dev.parent->bsddev);
324*63641805SEmmanuel Vadot 	bus_topo_unlock();
3251961a14aSEmmanuel Vadot 	if (error) {
3261961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
3271961a14aSEmmanuel Vadot 		  "failed to attach child: error %d\n", error);
328*63641805SEmmanuel Vadot 		sx_xunlock(&lkpi_sx_i2cbb);
3291961a14aSEmmanuel Vadot 		return (ENXIO);
3301961a14aSEmmanuel Vadot 	}
3311961a14aSEmmanuel Vadot 	LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter);
332*63641805SEmmanuel Vadot 	sx_xunlock(&lkpi_sx_i2cbb);
3331961a14aSEmmanuel Vadot 	return (0);
3341961a14aSEmmanuel Vadot }
335