xref: /freebsd/sys/compat/linuxkpi/common/src/linux_i2cbb.c (revision 8c13dd83a35b8e4f138ae13480535c6fe76b02d1)
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 
441961a14aSEmmanuel Vadot #include "iicbb_if.h"
451961a14aSEmmanuel Vadot #include "lkpi_iic_if.h"
461961a14aSEmmanuel Vadot 
471961a14aSEmmanuel Vadot static void lkpi_iicbb_setsda(device_t dev, int val);
481961a14aSEmmanuel Vadot static void lkpi_iicbb_setscl(device_t dev, int val);
491961a14aSEmmanuel Vadot static int lkpi_iicbb_getscl(device_t dev);
501961a14aSEmmanuel Vadot static int lkpi_iicbb_getsda(device_t dev);
511961a14aSEmmanuel Vadot static int lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
521961a14aSEmmanuel Vadot 
531961a14aSEmmanuel Vadot struct lkpi_iicbb_softc {
541961a14aSEmmanuel Vadot 	device_t		iicbb;
551961a14aSEmmanuel Vadot 	struct i2c_adapter	*adapter;
561961a14aSEmmanuel Vadot };
571961a14aSEmmanuel Vadot 
581961a14aSEmmanuel Vadot static int
591961a14aSEmmanuel Vadot lkpi_iicbb_probe(device_t dev)
601961a14aSEmmanuel Vadot {
611961a14aSEmmanuel Vadot 
621961a14aSEmmanuel Vadot 	device_set_desc(dev, "LinuxKPI I2CBB");
631961a14aSEmmanuel Vadot 	return (BUS_PROBE_NOWILDCARD);
641961a14aSEmmanuel Vadot }
651961a14aSEmmanuel Vadot 
661961a14aSEmmanuel Vadot static int
671961a14aSEmmanuel Vadot lkpi_iicbb_attach(device_t dev)
681961a14aSEmmanuel Vadot {
691961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
701961a14aSEmmanuel Vadot 
711961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
721961a14aSEmmanuel Vadot 	sc->iicbb = device_add_child(dev, "iicbb", -1);
731961a14aSEmmanuel Vadot 	if (sc->iicbb == NULL) {
741961a14aSEmmanuel Vadot 		device_printf(dev, "Couldn't add iicbb child, aborting\n");
751961a14aSEmmanuel Vadot 		return (ENXIO);
761961a14aSEmmanuel Vadot 	}
771961a14aSEmmanuel Vadot 	bus_generic_attach(dev);
781961a14aSEmmanuel Vadot 	return (0);
791961a14aSEmmanuel Vadot }
801961a14aSEmmanuel Vadot 
811961a14aSEmmanuel Vadot static int
821961a14aSEmmanuel Vadot lkpi_iicbb_detach(device_t dev)
831961a14aSEmmanuel Vadot {
841961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
851961a14aSEmmanuel Vadot 
861961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
871961a14aSEmmanuel Vadot 	if (sc->iicbb)
881961a14aSEmmanuel Vadot 		device_delete_child(dev, sc->iicbb);
891961a14aSEmmanuel Vadot 	return (0);
901961a14aSEmmanuel Vadot }
911961a14aSEmmanuel Vadot 
921961a14aSEmmanuel Vadot static int
931961a14aSEmmanuel Vadot lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter)
941961a14aSEmmanuel Vadot {
951961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
961961a14aSEmmanuel Vadot 
971961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
981961a14aSEmmanuel Vadot 	sc->adapter = adapter;
991961a14aSEmmanuel Vadot 
1001961a14aSEmmanuel Vadot 	return (0);
1011961a14aSEmmanuel Vadot }
1021961a14aSEmmanuel Vadot 
1031961a14aSEmmanuel Vadot static device_method_t lkpi_iicbb_methods[] = {
1041961a14aSEmmanuel Vadot 	/* device interface */
1051961a14aSEmmanuel Vadot 	DEVMETHOD(device_probe,		lkpi_iicbb_probe),
1061961a14aSEmmanuel Vadot 	DEVMETHOD(device_attach,	lkpi_iicbb_attach),
1071961a14aSEmmanuel Vadot 	DEVMETHOD(device_detach,	lkpi_iicbb_detach),
1081961a14aSEmmanuel Vadot 	DEVMETHOD(device_suspend,	bus_generic_suspend),
1091961a14aSEmmanuel Vadot 	DEVMETHOD(device_resume,	bus_generic_resume),
1101961a14aSEmmanuel Vadot 
1111961a14aSEmmanuel Vadot 	/* iicbb interface */
1121961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setsda,		lkpi_iicbb_setsda),
1131961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setscl,		lkpi_iicbb_setscl),
1141961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getsda,		lkpi_iicbb_getsda),
1151961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getscl,		lkpi_iicbb_getscl),
1161961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_reset,		lkpi_iicbb_reset),
1171961a14aSEmmanuel Vadot 
1181961a14aSEmmanuel Vadot 	/* lkpi_iicbb interface */
1191961a14aSEmmanuel Vadot 	DEVMETHOD(lkpi_iic_add_adapter,	lkpi_iicbb_add_adapter),
1201961a14aSEmmanuel Vadot 
1211961a14aSEmmanuel Vadot 	DEVMETHOD_END
1221961a14aSEmmanuel Vadot };
1231961a14aSEmmanuel Vadot 
1241961a14aSEmmanuel Vadot static devclass_t lkpi_iicbb_devclass;
1251961a14aSEmmanuel Vadot 
1261961a14aSEmmanuel Vadot driver_t lkpi_iicbb_driver = {
1271961a14aSEmmanuel Vadot 	"lkpi_iicbb",
1281961a14aSEmmanuel Vadot 	lkpi_iicbb_methods,
1291961a14aSEmmanuel Vadot 	sizeof(struct lkpi_iicbb_softc),
1301961a14aSEmmanuel Vadot };
1311961a14aSEmmanuel Vadot 
1321961a14aSEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, lkpi_iic, lkpi_iicbb_driver, lkpi_iicbb_devclass, 0, 0);
133*8c13dd83SJohn Baldwin DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, 0, 0);
1341961a14aSEmmanuel Vadot MODULE_DEPEND(lkpi_iicbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
1351961a14aSEmmanuel Vadot 
1361961a14aSEmmanuel Vadot static void
1371961a14aSEmmanuel Vadot lkpi_iicbb_setsda(device_t dev, int val)
1381961a14aSEmmanuel Vadot {
1391961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1401961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1411961a14aSEmmanuel Vadot 
1421961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1431961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
1441961a14aSEmmanuel Vadot 	algo_data->setsda(algo_data->data, val);
1451961a14aSEmmanuel Vadot 	cpu_spinwait();
1461961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
1471961a14aSEmmanuel Vadot }
1481961a14aSEmmanuel Vadot 
1491961a14aSEmmanuel Vadot static void
1501961a14aSEmmanuel Vadot lkpi_iicbb_setscl(device_t dev, int val)
1511961a14aSEmmanuel Vadot {
1521961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1531961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1541961a14aSEmmanuel Vadot 
1551961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1561961a14aSEmmanuel Vadot 
1571961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
1581961a14aSEmmanuel Vadot 	algo_data->setscl(algo_data->data, val);
1591961a14aSEmmanuel Vadot 	cpu_spinwait();
1601961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
1611961a14aSEmmanuel Vadot }
1621961a14aSEmmanuel Vadot 
1631961a14aSEmmanuel Vadot static int
1641961a14aSEmmanuel Vadot lkpi_iicbb_getscl(device_t dev)
1651961a14aSEmmanuel Vadot {
1661961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1671961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1681961a14aSEmmanuel Vadot 	unsigned long orig_ticks;
1691961a14aSEmmanuel Vadot 	int ret = 0;
1701961a14aSEmmanuel Vadot 
1711961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
1721961a14aSEmmanuel Vadot 
1731961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
1741961a14aSEmmanuel Vadot 
1751961a14aSEmmanuel Vadot 	orig_ticks = ticks;
1761961a14aSEmmanuel Vadot 	while (!ret) {
1771961a14aSEmmanuel Vadot 		ret = algo_data->getscl(algo_data->data);
1781961a14aSEmmanuel Vadot 
1791961a14aSEmmanuel Vadot 		if (ret)
1801961a14aSEmmanuel Vadot 			break;
1811961a14aSEmmanuel Vadot 
1821961a14aSEmmanuel Vadot 		if (ticks > orig_ticks + algo_data->timeout)
1831961a14aSEmmanuel Vadot 			return (ETIMEDOUT);
1841961a14aSEmmanuel Vadot 
1851961a14aSEmmanuel Vadot 		cpu_spinwait();
1861961a14aSEmmanuel Vadot 		DELAY(algo_data->udelay);
1871961a14aSEmmanuel Vadot 	}
1881961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
1891961a14aSEmmanuel Vadot 	return (ret);
1901961a14aSEmmanuel Vadot }
1911961a14aSEmmanuel Vadot 
1921961a14aSEmmanuel Vadot static int
1931961a14aSEmmanuel Vadot lkpi_iicbb_getsda(device_t dev)
1941961a14aSEmmanuel Vadot {
1951961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
1961961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
1971961a14aSEmmanuel Vadot 	int ret = 0;
1981961a14aSEmmanuel Vadot 
1991961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
2001961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
2011961a14aSEmmanuel Vadot 
2021961a14aSEmmanuel Vadot 	cpu_spinwait();
2031961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
2041961a14aSEmmanuel Vadot 	ret = algo_data->getsda(algo_data->data);
2051961a14aSEmmanuel Vadot 	cpu_spinwait();
2061961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
2071961a14aSEmmanuel Vadot 	return (ret);
2081961a14aSEmmanuel Vadot }
2091961a14aSEmmanuel Vadot 
2101961a14aSEmmanuel Vadot static int
2111961a14aSEmmanuel Vadot lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
2121961a14aSEmmanuel Vadot {
2131961a14aSEmmanuel Vadot 
2141961a14aSEmmanuel Vadot 	return (0);
2151961a14aSEmmanuel Vadot }
2161961a14aSEmmanuel Vadot 
2171961a14aSEmmanuel Vadot int
2181961a14aSEmmanuel Vadot lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs)
2191961a14aSEmmanuel Vadot {
2201961a14aSEmmanuel Vadot 
2211961a14aSEmmanuel Vadot 	/* TODO: convert from i2c_msg to iic_msg and call IICBUS_TRANFER */
2221961a14aSEmmanuel Vadot 	return (0);
2231961a14aSEmmanuel Vadot }
2241961a14aSEmmanuel Vadot 
2251961a14aSEmmanuel Vadot int
2261961a14aSEmmanuel Vadot lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter)
2271961a14aSEmmanuel Vadot {
2281961a14aSEmmanuel Vadot 	device_t lkpi_iicbb;
2291961a14aSEmmanuel Vadot 	int error;
2301961a14aSEmmanuel Vadot 
2311961a14aSEmmanuel Vadot 	if (bootverbose)
2321961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
2331961a14aSEmmanuel Vadot 		    "Adding i2c adapter %s\n", adapter->name);
2341961a14aSEmmanuel Vadot 	lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1);
2351961a14aSEmmanuel Vadot 	if (lkpi_iicbb == NULL) {
2361961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n");
2371961a14aSEmmanuel Vadot 		return (ENXIO);
2381961a14aSEmmanuel Vadot 	}
2391961a14aSEmmanuel Vadot 
2401961a14aSEmmanuel Vadot 	error = bus_generic_attach(adapter->dev.parent->bsddev);
2411961a14aSEmmanuel Vadot 	if (error) {
2421961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
2431961a14aSEmmanuel Vadot 		  "failed to attach child: error %d\n", error);
2441961a14aSEmmanuel Vadot 		return (ENXIO);
2451961a14aSEmmanuel Vadot 	}
2461961a14aSEmmanuel Vadot 	LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter);
2471961a14aSEmmanuel Vadot 	return (0);
2481961a14aSEmmanuel Vadot }
2491961a14aSEmmanuel Vadot 
250