1*1961a14aSEmmanuel Vadot /*- 2*1961a14aSEmmanuel Vadot * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG 3*1961a14aSEmmanuel Vadot * 4*1961a14aSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 5*1961a14aSEmmanuel Vadot * modification, are permitted provided that the following conditions 6*1961a14aSEmmanuel Vadot * are met: 7*1961a14aSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 8*1961a14aSEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 9*1961a14aSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 10*1961a14aSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 11*1961a14aSEmmanuel Vadot * documentation and/or other materials provided with the distribution. 12*1961a14aSEmmanuel Vadot * 13*1961a14aSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14*1961a14aSEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15*1961a14aSEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16*1961a14aSEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17*1961a14aSEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18*1961a14aSEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19*1961a14aSEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20*1961a14aSEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21*1961a14aSEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22*1961a14aSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23*1961a14aSEmmanuel Vadot * SUCH DAMAGE. 24*1961a14aSEmmanuel Vadot * 25*1961a14aSEmmanuel Vadot */ 26*1961a14aSEmmanuel Vadot 27*1961a14aSEmmanuel Vadot #include <sys/cdefs.h> 28*1961a14aSEmmanuel Vadot __FBSDID("$FreeBSD$"); 29*1961a14aSEmmanuel Vadot 30*1961a14aSEmmanuel Vadot #include <sys/param.h> 31*1961a14aSEmmanuel Vadot #include <sys/systm.h> 32*1961a14aSEmmanuel Vadot #include <sys/bus.h> 33*1961a14aSEmmanuel Vadot #include <sys/malloc.h> 34*1961a14aSEmmanuel Vadot 35*1961a14aSEmmanuel Vadot #include <dev/iicbus/iicbus.h> 36*1961a14aSEmmanuel Vadot #include <dev/iicbus/iiconf.h> 37*1961a14aSEmmanuel Vadot 38*1961a14aSEmmanuel Vadot #include <linux/device.h> 39*1961a14aSEmmanuel Vadot #include <linux/i2c.h> 40*1961a14aSEmmanuel Vadot #include <linux/i2c-algo-bit.h> 41*1961a14aSEmmanuel Vadot #include <linux/list.h> 42*1961a14aSEmmanuel Vadot #include <linux/pci.h> 43*1961a14aSEmmanuel Vadot 44*1961a14aSEmmanuel Vadot #include "iicbb_if.h" 45*1961a14aSEmmanuel Vadot #include "lkpi_iic_if.h" 46*1961a14aSEmmanuel Vadot 47*1961a14aSEmmanuel Vadot static void lkpi_iicbb_setsda(device_t dev, int val); 48*1961a14aSEmmanuel Vadot static void lkpi_iicbb_setscl(device_t dev, int val); 49*1961a14aSEmmanuel Vadot static int lkpi_iicbb_getscl(device_t dev); 50*1961a14aSEmmanuel Vadot static int lkpi_iicbb_getsda(device_t dev); 51*1961a14aSEmmanuel Vadot static int lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr); 52*1961a14aSEmmanuel Vadot 53*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc { 54*1961a14aSEmmanuel Vadot device_t iicbb; 55*1961a14aSEmmanuel Vadot struct i2c_adapter *adapter; 56*1961a14aSEmmanuel Vadot }; 57*1961a14aSEmmanuel Vadot 58*1961a14aSEmmanuel Vadot static int 59*1961a14aSEmmanuel Vadot lkpi_iicbb_probe(device_t dev) 60*1961a14aSEmmanuel Vadot { 61*1961a14aSEmmanuel Vadot 62*1961a14aSEmmanuel Vadot device_set_desc(dev, "LinuxKPI I2CBB"); 63*1961a14aSEmmanuel Vadot return (BUS_PROBE_NOWILDCARD); 64*1961a14aSEmmanuel Vadot } 65*1961a14aSEmmanuel Vadot 66*1961a14aSEmmanuel Vadot static int 67*1961a14aSEmmanuel Vadot lkpi_iicbb_attach(device_t dev) 68*1961a14aSEmmanuel Vadot { 69*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 70*1961a14aSEmmanuel Vadot 71*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 72*1961a14aSEmmanuel Vadot sc->iicbb = device_add_child(dev, "iicbb", -1); 73*1961a14aSEmmanuel Vadot if (sc->iicbb == NULL) { 74*1961a14aSEmmanuel Vadot device_printf(dev, "Couldn't add iicbb child, aborting\n"); 75*1961a14aSEmmanuel Vadot return (ENXIO); 76*1961a14aSEmmanuel Vadot } 77*1961a14aSEmmanuel Vadot bus_generic_attach(dev); 78*1961a14aSEmmanuel Vadot return (0); 79*1961a14aSEmmanuel Vadot } 80*1961a14aSEmmanuel Vadot 81*1961a14aSEmmanuel Vadot static int 82*1961a14aSEmmanuel Vadot lkpi_iicbb_detach(device_t dev) 83*1961a14aSEmmanuel Vadot { 84*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 85*1961a14aSEmmanuel Vadot 86*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 87*1961a14aSEmmanuel Vadot if (sc->iicbb) 88*1961a14aSEmmanuel Vadot device_delete_child(dev, sc->iicbb); 89*1961a14aSEmmanuel Vadot return (0); 90*1961a14aSEmmanuel Vadot } 91*1961a14aSEmmanuel Vadot 92*1961a14aSEmmanuel Vadot static int 93*1961a14aSEmmanuel Vadot lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter) 94*1961a14aSEmmanuel Vadot { 95*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 96*1961a14aSEmmanuel Vadot 97*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 98*1961a14aSEmmanuel Vadot sc->adapter = adapter; 99*1961a14aSEmmanuel Vadot 100*1961a14aSEmmanuel Vadot return (0); 101*1961a14aSEmmanuel Vadot } 102*1961a14aSEmmanuel Vadot 103*1961a14aSEmmanuel Vadot static device_method_t lkpi_iicbb_methods[] = { 104*1961a14aSEmmanuel Vadot /* device interface */ 105*1961a14aSEmmanuel Vadot DEVMETHOD(device_probe, lkpi_iicbb_probe), 106*1961a14aSEmmanuel Vadot DEVMETHOD(device_attach, lkpi_iicbb_attach), 107*1961a14aSEmmanuel Vadot DEVMETHOD(device_detach, lkpi_iicbb_detach), 108*1961a14aSEmmanuel Vadot DEVMETHOD(device_suspend, bus_generic_suspend), 109*1961a14aSEmmanuel Vadot DEVMETHOD(device_resume, bus_generic_resume), 110*1961a14aSEmmanuel Vadot 111*1961a14aSEmmanuel Vadot /* iicbb interface */ 112*1961a14aSEmmanuel Vadot DEVMETHOD(iicbb_setsda, lkpi_iicbb_setsda), 113*1961a14aSEmmanuel Vadot DEVMETHOD(iicbb_setscl, lkpi_iicbb_setscl), 114*1961a14aSEmmanuel Vadot DEVMETHOD(iicbb_getsda, lkpi_iicbb_getsda), 115*1961a14aSEmmanuel Vadot DEVMETHOD(iicbb_getscl, lkpi_iicbb_getscl), 116*1961a14aSEmmanuel Vadot DEVMETHOD(iicbb_reset, lkpi_iicbb_reset), 117*1961a14aSEmmanuel Vadot 118*1961a14aSEmmanuel Vadot /* lkpi_iicbb interface */ 119*1961a14aSEmmanuel Vadot DEVMETHOD(lkpi_iic_add_adapter, lkpi_iicbb_add_adapter), 120*1961a14aSEmmanuel Vadot 121*1961a14aSEmmanuel Vadot DEVMETHOD_END 122*1961a14aSEmmanuel Vadot }; 123*1961a14aSEmmanuel Vadot 124*1961a14aSEmmanuel Vadot static devclass_t lkpi_iicbb_devclass; 125*1961a14aSEmmanuel Vadot 126*1961a14aSEmmanuel Vadot driver_t lkpi_iicbb_driver = { 127*1961a14aSEmmanuel Vadot "lkpi_iicbb", 128*1961a14aSEmmanuel Vadot lkpi_iicbb_methods, 129*1961a14aSEmmanuel Vadot sizeof(struct lkpi_iicbb_softc), 130*1961a14aSEmmanuel Vadot }; 131*1961a14aSEmmanuel Vadot 132*1961a14aSEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, lkpi_iic, lkpi_iicbb_driver, lkpi_iicbb_devclass, 0, 0); 133*1961a14aSEmmanuel Vadot DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, iicbb_devclass, 0, 0); 134*1961a14aSEmmanuel Vadot MODULE_DEPEND(lkpi_iicbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); 135*1961a14aSEmmanuel Vadot 136*1961a14aSEmmanuel Vadot static void 137*1961a14aSEmmanuel Vadot lkpi_iicbb_setsda(device_t dev, int val) 138*1961a14aSEmmanuel Vadot { 139*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 140*1961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 141*1961a14aSEmmanuel Vadot 142*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 143*1961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 144*1961a14aSEmmanuel Vadot algo_data->setsda(algo_data->data, val); 145*1961a14aSEmmanuel Vadot cpu_spinwait(); 146*1961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 147*1961a14aSEmmanuel Vadot } 148*1961a14aSEmmanuel Vadot 149*1961a14aSEmmanuel Vadot static void 150*1961a14aSEmmanuel Vadot lkpi_iicbb_setscl(device_t dev, int val) 151*1961a14aSEmmanuel Vadot { 152*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 153*1961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 154*1961a14aSEmmanuel Vadot 155*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 156*1961a14aSEmmanuel Vadot 157*1961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 158*1961a14aSEmmanuel Vadot algo_data->setscl(algo_data->data, val); 159*1961a14aSEmmanuel Vadot cpu_spinwait(); 160*1961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 161*1961a14aSEmmanuel Vadot } 162*1961a14aSEmmanuel Vadot 163*1961a14aSEmmanuel Vadot static int 164*1961a14aSEmmanuel Vadot lkpi_iicbb_getscl(device_t dev) 165*1961a14aSEmmanuel Vadot { 166*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 167*1961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 168*1961a14aSEmmanuel Vadot unsigned long orig_ticks; 169*1961a14aSEmmanuel Vadot int ret = 0; 170*1961a14aSEmmanuel Vadot 171*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 172*1961a14aSEmmanuel Vadot 173*1961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 174*1961a14aSEmmanuel Vadot 175*1961a14aSEmmanuel Vadot orig_ticks = ticks; 176*1961a14aSEmmanuel Vadot while (!ret) { 177*1961a14aSEmmanuel Vadot ret = algo_data->getscl(algo_data->data); 178*1961a14aSEmmanuel Vadot 179*1961a14aSEmmanuel Vadot if (ret) 180*1961a14aSEmmanuel Vadot break; 181*1961a14aSEmmanuel Vadot 182*1961a14aSEmmanuel Vadot if (ticks > orig_ticks + algo_data->timeout) 183*1961a14aSEmmanuel Vadot return (ETIMEDOUT); 184*1961a14aSEmmanuel Vadot 185*1961a14aSEmmanuel Vadot cpu_spinwait(); 186*1961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 187*1961a14aSEmmanuel Vadot } 188*1961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 189*1961a14aSEmmanuel Vadot return (ret); 190*1961a14aSEmmanuel Vadot } 191*1961a14aSEmmanuel Vadot 192*1961a14aSEmmanuel Vadot static int 193*1961a14aSEmmanuel Vadot lkpi_iicbb_getsda(device_t dev) 194*1961a14aSEmmanuel Vadot { 195*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 196*1961a14aSEmmanuel Vadot struct i2c_algo_bit_data *algo_data; 197*1961a14aSEmmanuel Vadot int ret = 0; 198*1961a14aSEmmanuel Vadot 199*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 200*1961a14aSEmmanuel Vadot algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; 201*1961a14aSEmmanuel Vadot 202*1961a14aSEmmanuel Vadot cpu_spinwait(); 203*1961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 204*1961a14aSEmmanuel Vadot ret = algo_data->getsda(algo_data->data); 205*1961a14aSEmmanuel Vadot cpu_spinwait(); 206*1961a14aSEmmanuel Vadot DELAY(algo_data->udelay); 207*1961a14aSEmmanuel Vadot return (ret); 208*1961a14aSEmmanuel Vadot } 209*1961a14aSEmmanuel Vadot 210*1961a14aSEmmanuel Vadot static int 211*1961a14aSEmmanuel Vadot lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) 212*1961a14aSEmmanuel Vadot { 213*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc *sc; 214*1961a14aSEmmanuel Vadot 215*1961a14aSEmmanuel Vadot sc = device_get_softc(dev); 216*1961a14aSEmmanuel Vadot 217*1961a14aSEmmanuel Vadot return (0); 218*1961a14aSEmmanuel Vadot } 219*1961a14aSEmmanuel Vadot 220*1961a14aSEmmanuel Vadot int 221*1961a14aSEmmanuel Vadot lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) 222*1961a14aSEmmanuel Vadot { 223*1961a14aSEmmanuel Vadot 224*1961a14aSEmmanuel Vadot /* TODO: convert from i2c_msg to iic_msg and call IICBUS_TRANFER */ 225*1961a14aSEmmanuel Vadot return (0); 226*1961a14aSEmmanuel Vadot } 227*1961a14aSEmmanuel Vadot 228*1961a14aSEmmanuel Vadot int 229*1961a14aSEmmanuel Vadot lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter) 230*1961a14aSEmmanuel Vadot { 231*1961a14aSEmmanuel Vadot device_t lkpi_iicbb; 232*1961a14aSEmmanuel Vadot int error; 233*1961a14aSEmmanuel Vadot 234*1961a14aSEmmanuel Vadot if (bootverbose) 235*1961a14aSEmmanuel Vadot device_printf(adapter->dev.parent->bsddev, 236*1961a14aSEmmanuel Vadot "Adding i2c adapter %s\n", adapter->name); 237*1961a14aSEmmanuel Vadot lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1); 238*1961a14aSEmmanuel Vadot if (lkpi_iicbb == NULL) { 239*1961a14aSEmmanuel Vadot device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n"); 240*1961a14aSEmmanuel Vadot return (ENXIO); 241*1961a14aSEmmanuel Vadot } 242*1961a14aSEmmanuel Vadot 243*1961a14aSEmmanuel Vadot error = bus_generic_attach(adapter->dev.parent->bsddev); 244*1961a14aSEmmanuel Vadot if (error) { 245*1961a14aSEmmanuel Vadot device_printf(adapter->dev.parent->bsddev, 246*1961a14aSEmmanuel Vadot "failed to attach child: error %d\n", error); 247*1961a14aSEmmanuel Vadot return (ENXIO); 248*1961a14aSEmmanuel Vadot } 249*1961a14aSEmmanuel Vadot LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter); 250*1961a14aSEmmanuel Vadot return (0); 251*1961a14aSEmmanuel Vadot } 252*1961a14aSEmmanuel Vadot 253