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/param.h>
281961a14aSEmmanuel Vadot #include <sys/systm.h>
291961a14aSEmmanuel Vadot #include <sys/bus.h>
301961a14aSEmmanuel Vadot #include <sys/malloc.h>
311961a14aSEmmanuel Vadot 
321961a14aSEmmanuel Vadot #include <dev/iicbus/iicbus.h>
331961a14aSEmmanuel Vadot #include <dev/iicbus/iiconf.h>
341961a14aSEmmanuel Vadot 
351961a14aSEmmanuel Vadot #include <linux/device.h>
361961a14aSEmmanuel Vadot #include <linux/i2c.h>
371961a14aSEmmanuel Vadot #include <linux/i2c-algo-bit.h>
381961a14aSEmmanuel Vadot #include <linux/list.h>
391961a14aSEmmanuel Vadot #include <linux/pci.h>
401961a14aSEmmanuel Vadot 
4163641805SEmmanuel Vadot #include "iicbus_if.h"
421961a14aSEmmanuel Vadot #include "iicbb_if.h"
431961a14aSEmmanuel Vadot #include "lkpi_iic_if.h"
441961a14aSEmmanuel Vadot 
451961a14aSEmmanuel Vadot static void lkpi_iicbb_setsda(device_t dev, int val);
461961a14aSEmmanuel Vadot static void lkpi_iicbb_setscl(device_t dev, int val);
471961a14aSEmmanuel Vadot static int lkpi_iicbb_getscl(device_t dev);
481961a14aSEmmanuel Vadot static int lkpi_iicbb_getsda(device_t dev);
491961a14aSEmmanuel Vadot static int lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
5063641805SEmmanuel Vadot static int lkpi_iicbb_pre_xfer(device_t dev);
5163641805SEmmanuel Vadot static void lkpi_iicbb_post_xfer(device_t dev);
521961a14aSEmmanuel Vadot 
531961a14aSEmmanuel Vadot struct lkpi_iicbb_softc {
541961a14aSEmmanuel Vadot 	device_t		iicbb;
551961a14aSEmmanuel Vadot 	struct i2c_adapter	*adapter;
561961a14aSEmmanuel Vadot };
571961a14aSEmmanuel Vadot 
5863641805SEmmanuel Vadot static struct sx lkpi_sx_i2cbb;
5963641805SEmmanuel Vadot 
6063641805SEmmanuel Vadot static void
lkpi_sysinit_i2cbb(void * arg __unused)6163641805SEmmanuel Vadot lkpi_sysinit_i2cbb(void *arg __unused)
6263641805SEmmanuel Vadot {
6363641805SEmmanuel Vadot 
6463641805SEmmanuel Vadot 	sx_init(&lkpi_sx_i2cbb, "lkpi-i2cbb");
6563641805SEmmanuel Vadot }
6663641805SEmmanuel Vadot 
6763641805SEmmanuel Vadot static void
lkpi_sysuninit_i2cbb(void * arg __unused)6863641805SEmmanuel Vadot lkpi_sysuninit_i2cbb(void *arg __unused)
6963641805SEmmanuel Vadot {
7063641805SEmmanuel Vadot 
7163641805SEmmanuel Vadot 	sx_destroy(&lkpi_sx_i2cbb);
7263641805SEmmanuel Vadot }
7363641805SEmmanuel Vadot 
7463641805SEmmanuel Vadot SYSINIT(lkpi_i2cbb, SI_SUB_DRIVERS, SI_ORDER_ANY,
7563641805SEmmanuel Vadot     lkpi_sysinit_i2cbb, NULL);
7663641805SEmmanuel Vadot SYSUNINIT(lkpi_i2cbb, SI_SUB_DRIVERS, SI_ORDER_ANY,
7763641805SEmmanuel Vadot     lkpi_sysuninit_i2cbb, NULL);
7863641805SEmmanuel Vadot 
791961a14aSEmmanuel Vadot static int
lkpi_iicbb_probe(device_t dev)801961a14aSEmmanuel Vadot lkpi_iicbb_probe(device_t dev)
811961a14aSEmmanuel Vadot {
821961a14aSEmmanuel Vadot 
831961a14aSEmmanuel Vadot 	device_set_desc(dev, "LinuxKPI I2CBB");
841961a14aSEmmanuel Vadot 	return (BUS_PROBE_NOWILDCARD);
851961a14aSEmmanuel Vadot }
861961a14aSEmmanuel Vadot 
871961a14aSEmmanuel Vadot static int
lkpi_iicbb_attach(device_t dev)881961a14aSEmmanuel Vadot lkpi_iicbb_attach(device_t dev)
891961a14aSEmmanuel Vadot {
901961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
911961a14aSEmmanuel Vadot 
921961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
931961a14aSEmmanuel Vadot 	sc->iicbb = device_add_child(dev, "iicbb", -1);
941961a14aSEmmanuel Vadot 	if (sc->iicbb == NULL) {
951961a14aSEmmanuel Vadot 		device_printf(dev, "Couldn't add iicbb child, aborting\n");
961961a14aSEmmanuel Vadot 		return (ENXIO);
971961a14aSEmmanuel Vadot 	}
981961a14aSEmmanuel Vadot 	bus_generic_attach(dev);
991961a14aSEmmanuel Vadot 	return (0);
1001961a14aSEmmanuel Vadot }
1011961a14aSEmmanuel Vadot 
1021961a14aSEmmanuel Vadot static int
lkpi_iicbb_detach(device_t dev)1031961a14aSEmmanuel Vadot lkpi_iicbb_detach(device_t dev)
1041961a14aSEmmanuel Vadot {
1051961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1061961a14aSEmmanuel Vadot 
1071961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1081961a14aSEmmanuel Vadot 	if (sc->iicbb)
1091961a14aSEmmanuel Vadot 		device_delete_child(dev, sc->iicbb);
1101961a14aSEmmanuel Vadot 	return (0);
1111961a14aSEmmanuel Vadot }
1121961a14aSEmmanuel Vadot 
1131961a14aSEmmanuel Vadot static int
lkpi_iicbb_add_adapter(device_t dev,struct i2c_adapter * adapter)1141961a14aSEmmanuel Vadot lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter)
1151961a14aSEmmanuel Vadot {
1161961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
11763641805SEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1181961a14aSEmmanuel Vadot 
1191961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1201961a14aSEmmanuel Vadot 	sc->adapter = adapter;
1211961a14aSEmmanuel Vadot 
12263641805SEmmanuel Vadot 	/*
12363641805SEmmanuel Vadot 	 * Set iicbb timing parameters deriving speed from the protocol delay.
12463641805SEmmanuel Vadot 	 */
12563641805SEmmanuel Vadot 	algo_data = adapter->algo_data;
12663641805SEmmanuel Vadot 	if (algo_data->udelay != 0)
12763641805SEmmanuel Vadot 		IICBUS_RESET(sc->iicbb, 1000000 / algo_data->udelay, 0, NULL);
1281961a14aSEmmanuel Vadot 	return (0);
1291961a14aSEmmanuel Vadot }
1301961a14aSEmmanuel Vadot 
13125d21a84SEmmanuel Vadot static struct i2c_adapter *
lkpi_iicbb_get_adapter(device_t dev)13225d21a84SEmmanuel Vadot lkpi_iicbb_get_adapter(device_t dev)
13325d21a84SEmmanuel Vadot {
13425d21a84SEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
13525d21a84SEmmanuel Vadot 
13625d21a84SEmmanuel Vadot 	sc = device_get_softc(dev);
13725d21a84SEmmanuel Vadot 	return (sc->adapter);
13825d21a84SEmmanuel Vadot }
13925d21a84SEmmanuel Vadot 
1401961a14aSEmmanuel Vadot static device_method_t lkpi_iicbb_methods[] = {
1411961a14aSEmmanuel Vadot 	/* device interface */
1421961a14aSEmmanuel Vadot 	DEVMETHOD(device_probe,		lkpi_iicbb_probe),
1431961a14aSEmmanuel Vadot 	DEVMETHOD(device_attach,	lkpi_iicbb_attach),
1441961a14aSEmmanuel Vadot 	DEVMETHOD(device_detach,	lkpi_iicbb_detach),
1451961a14aSEmmanuel Vadot 	DEVMETHOD(device_suspend,	bus_generic_suspend),
1461961a14aSEmmanuel Vadot 	DEVMETHOD(device_resume,	bus_generic_resume),
1471961a14aSEmmanuel Vadot 
1481961a14aSEmmanuel Vadot 	/* iicbb interface */
1491961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setsda,		lkpi_iicbb_setsda),
1501961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setscl,		lkpi_iicbb_setscl),
1511961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getsda,		lkpi_iicbb_getsda),
1521961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getscl,		lkpi_iicbb_getscl),
1531961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_reset,		lkpi_iicbb_reset),
15463641805SEmmanuel Vadot 	DEVMETHOD(iicbb_pre_xfer,	lkpi_iicbb_pre_xfer),
15563641805SEmmanuel Vadot 	DEVMETHOD(iicbb_post_xfer,	lkpi_iicbb_post_xfer),
1561961a14aSEmmanuel Vadot 
1571961a14aSEmmanuel Vadot 	/* lkpi_iicbb interface */
1581961a14aSEmmanuel Vadot 	DEVMETHOD(lkpi_iic_add_adapter,	lkpi_iicbb_add_adapter),
15925d21a84SEmmanuel Vadot 	DEVMETHOD(lkpi_iic_get_adapter,	lkpi_iicbb_get_adapter),
1601961a14aSEmmanuel Vadot 
1611961a14aSEmmanuel Vadot 	DEVMETHOD_END
1621961a14aSEmmanuel Vadot };
1631961a14aSEmmanuel Vadot 
1641961a14aSEmmanuel Vadot driver_t lkpi_iicbb_driver = {
1651961a14aSEmmanuel Vadot 	"lkpi_iicbb",
1661961a14aSEmmanuel Vadot 	lkpi_iicbb_methods,
1671961a14aSEmmanuel Vadot 	sizeof(struct lkpi_iicbb_softc),
1681961a14aSEmmanuel Vadot };
1691961a14aSEmmanuel Vadot 
17063641805SEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, drmn, lkpi_iicbb_driver, 0, 0);
17163641805SEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, drm, lkpi_iicbb_driver, 0, 0);
1728c13dd83SJohn Baldwin DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, 0, 0);
17363641805SEmmanuel Vadot MODULE_DEPEND(linuxkpi, iicbb, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1741961a14aSEmmanuel Vadot 
1751961a14aSEmmanuel Vadot static void
lkpi_iicbb_setsda(device_t dev,int val)1761961a14aSEmmanuel Vadot lkpi_iicbb_setsda(device_t dev, int val)
1771961a14aSEmmanuel Vadot {
1781961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1791961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1801961a14aSEmmanuel Vadot 
1811961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
18263641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
1831961a14aSEmmanuel Vadot 	algo_data->setsda(algo_data->data, val);
1841961a14aSEmmanuel Vadot }
1851961a14aSEmmanuel Vadot 
1861961a14aSEmmanuel Vadot static void
lkpi_iicbb_setscl(device_t dev,int val)1871961a14aSEmmanuel Vadot lkpi_iicbb_setscl(device_t dev, int val)
1881961a14aSEmmanuel Vadot {
1891961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1901961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1911961a14aSEmmanuel Vadot 
1921961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
19363641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
1941961a14aSEmmanuel Vadot 	algo_data->setscl(algo_data->data, val);
1951961a14aSEmmanuel Vadot }
1961961a14aSEmmanuel Vadot 
1971961a14aSEmmanuel Vadot static int
lkpi_iicbb_getscl(device_t dev)1981961a14aSEmmanuel Vadot lkpi_iicbb_getscl(device_t dev)
1991961a14aSEmmanuel Vadot {
2001961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
2011961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
20263641805SEmmanuel Vadot 	int ret;
2031961a14aSEmmanuel Vadot 
2041961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
20563641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
2061961a14aSEmmanuel Vadot 	ret = algo_data->getscl(algo_data->data);
2071961a14aSEmmanuel Vadot 	return (ret);
2081961a14aSEmmanuel Vadot }
2091961a14aSEmmanuel Vadot 
2101961a14aSEmmanuel Vadot static int
lkpi_iicbb_getsda(device_t dev)2111961a14aSEmmanuel Vadot lkpi_iicbb_getsda(device_t dev)
2121961a14aSEmmanuel Vadot {
2131961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
2141961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
21563641805SEmmanuel Vadot 	int ret;
2161961a14aSEmmanuel Vadot 
2171961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
21863641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
2191961a14aSEmmanuel Vadot 	ret = algo_data->getsda(algo_data->data);
2201961a14aSEmmanuel Vadot 	return (ret);
2211961a14aSEmmanuel Vadot }
2221961a14aSEmmanuel Vadot 
2231961a14aSEmmanuel Vadot static int
lkpi_iicbb_reset(device_t dev,u_char speed,u_char addr,u_char * oldaddr)2241961a14aSEmmanuel Vadot lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
2251961a14aSEmmanuel Vadot {
2261961a14aSEmmanuel Vadot 
22763641805SEmmanuel Vadot 	/* That doesn't seems to be supported in linux */
2281961a14aSEmmanuel Vadot 	return (0);
2291961a14aSEmmanuel Vadot }
2301961a14aSEmmanuel Vadot 
23163641805SEmmanuel Vadot static int
lkpi_iicbb_pre_xfer(device_t dev)23263641805SEmmanuel Vadot lkpi_iicbb_pre_xfer(device_t dev)
2331961a14aSEmmanuel Vadot {
23463641805SEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
23563641805SEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
23663641805SEmmanuel Vadot 	int rc = 0;
2371961a14aSEmmanuel Vadot 
23863641805SEmmanuel Vadot 	sc = device_get_softc(dev);
23963641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
24063641805SEmmanuel Vadot 	if (algo_data->pre_xfer != 0)
24163641805SEmmanuel Vadot 		rc = algo_data->pre_xfer(sc->adapter);
24263641805SEmmanuel Vadot 	return (rc);
24363641805SEmmanuel Vadot }
24463641805SEmmanuel Vadot 
24563641805SEmmanuel Vadot static void
lkpi_iicbb_post_xfer(device_t dev)24663641805SEmmanuel Vadot lkpi_iicbb_post_xfer(device_t dev)
24763641805SEmmanuel Vadot {
24863641805SEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
24963641805SEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
25063641805SEmmanuel Vadot 
25163641805SEmmanuel Vadot 	sc = device_get_softc(dev);
25263641805SEmmanuel Vadot 	algo_data = sc->adapter->algo_data;
25363641805SEmmanuel Vadot 	if (algo_data->post_xfer != NULL)
25463641805SEmmanuel Vadot 		algo_data->post_xfer(sc->adapter);
25563641805SEmmanuel Vadot }
25663641805SEmmanuel Vadot 
25763641805SEmmanuel Vadot int
lkpi_i2cbb_transfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int nmsgs)25863641805SEmmanuel Vadot lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
25963641805SEmmanuel Vadot     int nmsgs)
26063641805SEmmanuel Vadot {
26163641805SEmmanuel Vadot 	struct iic_msg *bsd_msgs;
26263641805SEmmanuel Vadot 	int ret = ENXIO;
26363641805SEmmanuel Vadot 
26463641805SEmmanuel Vadot 	linux_set_current(curthread);
26563641805SEmmanuel Vadot 
26663641805SEmmanuel Vadot 	bsd_msgs = malloc(sizeof(struct iic_msg) * nmsgs,
26763641805SEmmanuel Vadot 	    M_DEVBUF, M_WAITOK | M_ZERO);
26863641805SEmmanuel Vadot 
26963641805SEmmanuel Vadot 	for (int i = 0; i < nmsgs; i++) {
27063641805SEmmanuel Vadot 		bsd_msgs[i].slave = msgs[i].addr << 1;
27163641805SEmmanuel Vadot 		bsd_msgs[i].len = msgs[i].len;
27263641805SEmmanuel Vadot 		bsd_msgs[i].buf = msgs[i].buf;
27363641805SEmmanuel Vadot 		if (msgs[i].flags & I2C_M_RD)
27463641805SEmmanuel Vadot 			bsd_msgs[i].flags |= IIC_M_RD;
27563641805SEmmanuel Vadot 		if (msgs[i].flags & I2C_M_NOSTART)
27663641805SEmmanuel Vadot 			bsd_msgs[i].flags |= IIC_M_NOSTART;
27763641805SEmmanuel Vadot 	}
27863641805SEmmanuel Vadot 
27963641805SEmmanuel Vadot 	for (int unit = 0; ; unit++) {
28063641805SEmmanuel Vadot 		device_t child;
28163641805SEmmanuel Vadot 		struct lkpi_iicbb_softc *sc;
28263641805SEmmanuel Vadot 
28363641805SEmmanuel Vadot 		child = device_find_child(adapter->dev.parent->bsddev,
28463641805SEmmanuel Vadot 		    "lkpi_iicbb", unit);
28563641805SEmmanuel Vadot 		if (child == NULL)
28663641805SEmmanuel Vadot 			break;
28763641805SEmmanuel Vadot 		if (adapter == LKPI_IIC_GET_ADAPTER(child)) {
28863641805SEmmanuel Vadot 			sc = device_get_softc(child);
28963641805SEmmanuel Vadot 			ret = IICBUS_TRANSFER(sc->iicbb, bsd_msgs, nmsgs);
29063641805SEmmanuel Vadot 			ret = iic2errno(ret);
29163641805SEmmanuel Vadot 			break;
29263641805SEmmanuel Vadot 		}
29363641805SEmmanuel Vadot 	}
29463641805SEmmanuel Vadot 
29563641805SEmmanuel Vadot 	free(bsd_msgs, M_DEVBUF);
29663641805SEmmanuel Vadot 
29763641805SEmmanuel Vadot 	if (ret != 0)
29863641805SEmmanuel Vadot 		return (-ret);
29963641805SEmmanuel Vadot 	return (nmsgs);
3001961a14aSEmmanuel Vadot }
3011961a14aSEmmanuel Vadot 
3021961a14aSEmmanuel Vadot int
lkpi_i2c_bit_add_bus(struct i2c_adapter * adapter)3031961a14aSEmmanuel Vadot lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter)
3041961a14aSEmmanuel Vadot {
3051961a14aSEmmanuel Vadot 	device_t lkpi_iicbb;
3061961a14aSEmmanuel Vadot 	int error;
3071961a14aSEmmanuel Vadot 
3081961a14aSEmmanuel Vadot 	if (bootverbose)
3091961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
3101961a14aSEmmanuel Vadot 		    "Adding i2c adapter %s\n", adapter->name);
31163641805SEmmanuel Vadot 	sx_xlock(&lkpi_sx_i2cbb);
3121961a14aSEmmanuel Vadot 	lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1);
3131961a14aSEmmanuel Vadot 	if (lkpi_iicbb == NULL) {
3141961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n");
31563641805SEmmanuel Vadot 		sx_xunlock(&lkpi_sx_i2cbb);
3161961a14aSEmmanuel Vadot 		return (ENXIO);
3171961a14aSEmmanuel Vadot 	}
3181961a14aSEmmanuel Vadot 
31963641805SEmmanuel Vadot 	bus_topo_lock();
3201961a14aSEmmanuel Vadot 	error = bus_generic_attach(adapter->dev.parent->bsddev);
32163641805SEmmanuel Vadot 	bus_topo_unlock();
3221961a14aSEmmanuel Vadot 	if (error) {
3231961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
3241961a14aSEmmanuel Vadot 		  "failed to attach child: error %d\n", error);
32563641805SEmmanuel Vadot 		sx_xunlock(&lkpi_sx_i2cbb);
3261961a14aSEmmanuel Vadot 		return (ENXIO);
3271961a14aSEmmanuel Vadot 	}
3281961a14aSEmmanuel Vadot 	LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter);
32963641805SEmmanuel Vadot 	sx_xunlock(&lkpi_sx_i2cbb);
3301961a14aSEmmanuel Vadot 	return (0);
3311961a14aSEmmanuel Vadot }
332