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