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 103*25d21a84SEmmanuel Vadot static struct i2c_adapter * 104*25d21a84SEmmanuel Vadot lkpi_iicbb_get_adapter(device_t dev) 105*25d21a84SEmmanuel Vadot { 106*25d21a84SEmmanuel Vadot struct lkpi_iicbb_softc *sc; 107*25d21a84SEmmanuel Vadot 108*25d21a84SEmmanuel Vadot sc = device_get_softc(dev); 109*25d21a84SEmmanuel Vadot return (sc->adapter); 110*25d21a84SEmmanuel Vadot } 111*25d21a84SEmmanuel Vadot 1121961a14aSEmmanuel Vadot static device_method_t lkpi_iicbb_methods[] = { 1131961a14aSEmmanuel Vadot /* device interface */ 1141961a14aSEmmanuel Vadot DEVMETHOD(device_probe, lkpi_iicbb_probe), 1151961a14aSEmmanuel Vadot DEVMETHOD(device_attach, lkpi_iicbb_attach), 1161961a14aSEmmanuel Vadot DEVMETHOD(device_detach, lkpi_iicbb_detach), 1171961a14aSEmmanuel Vadot DEVMETHOD(device_suspend, bus_generic_suspend), 1181961a14aSEmmanuel Vadot DEVMETHOD(device_resume, bus_generic_resume), 1191961a14aSEmmanuel Vadot 1201961a14aSEmmanuel Vadot /* iicbb interface */ 1211961a14aSEmmanuel Vadot DEVMETHOD(iicbb_setsda, lkpi_iicbb_setsda), 1221961a14aSEmmanuel Vadot DEVMETHOD(iicbb_setscl, lkpi_iicbb_setscl), 1231961a14aSEmmanuel Vadot DEVMETHOD(iicbb_getsda, lkpi_iicbb_getsda), 1241961a14aSEmmanuel Vadot DEVMETHOD(iicbb_getscl, lkpi_iicbb_getscl), 1251961a14aSEmmanuel Vadot DEVMETHOD(iicbb_reset, lkpi_iicbb_reset), 1261961a14aSEmmanuel Vadot 1271961a14aSEmmanuel Vadot /* lkpi_iicbb interface */ 1281961a14aSEmmanuel Vadot DEVMETHOD(lkpi_iic_add_adapter, lkpi_iicbb_add_adapter), 129*25d21a84SEmmanuel Vadot DEVMETHOD(lkpi_iic_get_adapter, lkpi_iicbb_get_adapter), 1301961a14aSEmmanuel Vadot 1311961a14aSEmmanuel Vadot DEVMETHOD_END 1321961a14aSEmmanuel Vadot }; 1331961a14aSEmmanuel Vadot 1341961a14aSEmmanuel Vadot driver_t lkpi_iicbb_driver = { 1351961a14aSEmmanuel Vadot "lkpi_iicbb", 1361961a14aSEmmanuel Vadot lkpi_iicbb_methods, 1371961a14aSEmmanuel Vadot sizeof(struct lkpi_iicbb_softc), 1381961a14aSEmmanuel Vadot }; 1391961a14aSEmmanuel Vadot 140a65d0774SJohn Baldwin DRIVER_MODULE(lkpi_iicbb, lkpi_iic, lkpi_iicbb_driver, 0, 0); 1418c13dd83SJohn Baldwin DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, 0, 0); 1421961a14aSEmmanuel Vadot MODULE_DEPEND(lkpi_iicbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); 1431961a14aSEmmanuel Vadot 1441961a14aSEmmanuel Vadot static void 1451961a14aSEmmanuel Vadot lkpi_iicbb_setsda(device_t dev, int val) 1461961a14aSEmmanuel Vadot { 1471961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 1481961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 1491961a14aSEmmanuel Vadot 1501961a14aSEmmanuel Vadot sc = device_get_softc(dev); 1511961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 1521961a14aSEmmanuel Vadot algo_data->setsda(algo_data->data, val); 1531961a14aSEmmanuel Vadot cpu_spinwait(); 1541961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 1551961a14aSEmmanuel Vadot } 1561961a14aSEmmanuel Vadot 1571961a14aSEmmanuel Vadot static void 1581961a14aSEmmanuel Vadot lkpi_iicbb_setscl(device_t dev, int val) 1591961a14aSEmmanuel Vadot { 1601961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 1611961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 1621961a14aSEmmanuel Vadot 1631961a14aSEmmanuel Vadot sc = device_get_softc(dev); 1641961a14aSEmmanuel Vadot 1651961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 1661961a14aSEmmanuel Vadot algo_data->setscl(algo_data->data, val); 1671961a14aSEmmanuel Vadot cpu_spinwait(); 1681961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 1691961a14aSEmmanuel Vadot } 1701961a14aSEmmanuel Vadot 1711961a14aSEmmanuel Vadot static int 1721961a14aSEmmanuel Vadot lkpi_iicbb_getscl(device_t dev) 1731961a14aSEmmanuel Vadot { 1741961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 1751961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 1761961a14aSEmmanuel Vadot unsigned long orig_ticks; 1771961a14aSEmmanuel Vadot int ret = 0; 1781961a14aSEmmanuel Vadot 1791961a14aSEmmanuel Vadot sc = device_get_softc(dev); 1801961a14aSEmmanuel Vadot 1811961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 1821961a14aSEmmanuel Vadot 1831961a14aSEmmanuel Vadot orig_ticks = ticks; 1841961a14aSEmmanuel Vadot while (!ret) { 1851961a14aSEmmanuel Vadot ret = algo_data->getscl(algo_data->data); 1861961a14aSEmmanuel Vadot 1871961a14aSEmmanuel Vadot if (ret) 1881961a14aSEmmanuel Vadot break; 1891961a14aSEmmanuel Vadot 1901961a14aSEmmanuel Vadot if (ticks > orig_ticks + algo_data->timeout) 1911961a14aSEmmanuel Vadot return (ETIMEDOUT); 1921961a14aSEmmanuel Vadot 1931961a14aSEmmanuel Vadot cpu_spinwait(); 1941961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 1951961a14aSEmmanuel Vadot } 1961961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 1971961a14aSEmmanuel Vadot return (ret); 1981961a14aSEmmanuel Vadot } 1991961a14aSEmmanuel Vadot 2001961a14aSEmmanuel Vadot static int 2011961a14aSEmmanuel Vadot lkpi_iicbb_getsda(device_t dev) 2021961a14aSEmmanuel Vadot { 2031961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 2041961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 2051961a14aSEmmanuel Vadot int ret = 0; 2061961a14aSEmmanuel Vadot 2071961a14aSEmmanuel Vadot sc = device_get_softc(dev); 2081961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 2091961a14aSEmmanuel Vadot 2101961a14aSEmmanuel Vadot cpu_spinwait(); 2111961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 2121961a14aSEmmanuel Vadot ret = algo_data->getsda(algo_data->data); 2131961a14aSEmmanuel Vadot cpu_spinwait(); 2141961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 2151961a14aSEmmanuel Vadot return (ret); 2161961a14aSEmmanuel Vadot } 2171961a14aSEmmanuel Vadot 2181961a14aSEmmanuel Vadot static int 2191961a14aSEmmanuel Vadot lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) 2201961a14aSEmmanuel Vadot { 2211961a14aSEmmanuel Vadot 2221961a14aSEmmanuel Vadot return (0); 2231961a14aSEmmanuel Vadot } 2241961a14aSEmmanuel Vadot 2251961a14aSEmmanuel Vadot int 2261961a14aSEmmanuel Vadot lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) 2271961a14aSEmmanuel Vadot { 2281961a14aSEmmanuel Vadot 2291961a14aSEmmanuel Vadot /* TODO: convert from i2c_msg to iic_msg and call IICBUS_TRANFER */ 2301961a14aSEmmanuel Vadot return (0); 2311961a14aSEmmanuel Vadot } 2321961a14aSEmmanuel Vadot 2331961a14aSEmmanuel Vadot int 2341961a14aSEmmanuel Vadot lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter) 2351961a14aSEmmanuel Vadot { 2361961a14aSEmmanuel Vadot device_t lkpi_iicbb; 2371961a14aSEmmanuel Vadot int error; 2381961a14aSEmmanuel Vadot 2391961a14aSEmmanuel Vadot if (bootverbose) 2401961a14aSEmmanuel Vadot device_printf(adapter->dev.parent->bsddev, 2411961a14aSEmmanuel Vadot "Adding i2c adapter %s\n", adapter->name); 2421961a14aSEmmanuel Vadot lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1); 2431961a14aSEmmanuel Vadot if (lkpi_iicbb == NULL) { 2441961a14aSEmmanuel Vadot device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n"); 2451961a14aSEmmanuel Vadot return (ENXIO); 2461961a14aSEmmanuel Vadot } 2471961a14aSEmmanuel Vadot 2481961a14aSEmmanuel Vadot error = bus_generic_attach(adapter->dev.parent->bsddev); 2491961a14aSEmmanuel Vadot if (error) { 2501961a14aSEmmanuel Vadot device_printf(adapter->dev.parent->bsddev, 2511961a14aSEmmanuel Vadot "failed to attach child: error %d\n", error); 2521961a14aSEmmanuel Vadot return (ENXIO); 2531961a14aSEmmanuel Vadot } 2541961a14aSEmmanuel Vadot LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter); 2551961a14aSEmmanuel Vadot return (0); 2561961a14aSEmmanuel Vadot } 2571961a14aSEmmanuel Vadot 258