1*9f4ca867SFrançois Tigeot /* 2*9f4ca867SFrançois Tigeot * Copyright (c) 2016 François Tigeot 3*9f4ca867SFrançois Tigeot * All rights reserved. 4*9f4ca867SFrançois Tigeot * 5*9f4ca867SFrançois Tigeot * Redistribution and use in source and binary forms, with or without 6*9f4ca867SFrançois Tigeot * modification, are permitted provided that the following conditions 7*9f4ca867SFrançois Tigeot * are met: 8*9f4ca867SFrançois Tigeot * 1. Redistributions of source code must retain the above copyright 9*9f4ca867SFrançois Tigeot * notice unmodified, this list of conditions, and the following 10*9f4ca867SFrançois Tigeot * disclaimer. 11*9f4ca867SFrançois Tigeot * 2. Redistributions in binary form must reproduce the above copyright 12*9f4ca867SFrançois Tigeot * notice, this list of conditions and the following disclaimer in the 13*9f4ca867SFrançois Tigeot * documentation and/or other materials provided with the distribution. 14*9f4ca867SFrançois Tigeot * 15*9f4ca867SFrançois Tigeot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*9f4ca867SFrançois Tigeot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*9f4ca867SFrançois Tigeot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*9f4ca867SFrançois Tigeot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*9f4ca867SFrançois Tigeot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*9f4ca867SFrançois Tigeot * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*9f4ca867SFrançois Tigeot * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*9f4ca867SFrançois Tigeot * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*9f4ca867SFrançois Tigeot * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*9f4ca867SFrançois Tigeot * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*9f4ca867SFrançois Tigeot */ 26*9f4ca867SFrançois Tigeot 27*9f4ca867SFrançois Tigeot #include <linux/i2c.h> 28*9f4ca867SFrançois Tigeot #include <linux/i2c-algo-bit.h> 29*9f4ca867SFrançois Tigeot 30*9f4ca867SFrançois Tigeot static struct lock i2c_lock; 31*9f4ca867SFrançois Tigeot LOCK_SYSINIT(i2c_lock, &i2c_lock, "i2cl", LK_CANRECURSE); 32*9f4ca867SFrançois Tigeot 33*9f4ca867SFrançois Tigeot int 34*9f4ca867SFrançois Tigeot i2c_add_adapter(struct i2c_adapter *adapter) 35*9f4ca867SFrançois Tigeot { 36*9f4ca867SFrançois Tigeot /* Linux registers a unique bus number here */ 37*9f4ca867SFrançois Tigeot return 0; 38*9f4ca867SFrançois Tigeot } 39*9f4ca867SFrançois Tigeot 40*9f4ca867SFrançois Tigeot void 41*9f4ca867SFrançois Tigeot i2c_del_adapter(struct i2c_adapter *adapter) 42*9f4ca867SFrançois Tigeot { 43*9f4ca867SFrançois Tigeot /* Linux deletes a unique bus number here */ 44*9f4ca867SFrançois Tigeot } 45*9f4ca867SFrançois Tigeot 46*9f4ca867SFrançois Tigeot /* 47*9f4ca867SFrançois Tigeot * i2c_transfer() 48*9f4ca867SFrançois Tigeot * The original Linux implementation does: 49*9f4ca867SFrançois Tigeot * 1. return -EOPNOTSUPP if adapter->algo->master_xfer is NULL 50*9f4ca867SFrançois Tigeot * 2. try to transfer msgs by calling adapter->algo->master_xfer() 51*9f4ca867SFrançois Tigeot * 3. if it took more ticks than adapter->timeout, fail 52*9f4ca867SFrançois Tigeot * 4. if the transfer failed, retry up to adapter->retries times 53*9f4ca867SFrançois Tigeot * 5. return the result of the last call of adapter->algo->master_xfer() 54*9f4ca867SFrançois Tigeot */ 55*9f4ca867SFrançois Tigeot int 56*9f4ca867SFrançois Tigeot i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) 57*9f4ca867SFrançois Tigeot { 58*9f4ca867SFrançois Tigeot uint64_t start_ticks; 59*9f4ca867SFrançois Tigeot int ret, tries = 0; 60*9f4ca867SFrançois Tigeot 61*9f4ca867SFrançois Tigeot if (adapter->algo->master_xfer == NULL) 62*9f4ca867SFrançois Tigeot return -EOPNOTSUPP; 63*9f4ca867SFrançois Tigeot 64*9f4ca867SFrançois Tigeot lockmgr(&i2c_lock, LK_EXCLUSIVE); 65*9f4ca867SFrançois Tigeot start_ticks = ticks; 66*9f4ca867SFrançois Tigeot do { 67*9f4ca867SFrançois Tigeot ret = adapter->algo->master_xfer(adapter, msgs, num); 68*9f4ca867SFrançois Tigeot if (ticks > start_ticks + adapter->timeout) 69*9f4ca867SFrançois Tigeot break; 70*9f4ca867SFrançois Tigeot if (ret != -EAGAIN) 71*9f4ca867SFrançois Tigeot break; 72*9f4ca867SFrançois Tigeot tries++; 73*9f4ca867SFrançois Tigeot } while (tries < adapter->retries); 74*9f4ca867SFrançois Tigeot lockmgr(&i2c_lock, LK_RELEASE); 75*9f4ca867SFrançois Tigeot 76*9f4ca867SFrançois Tigeot return ret; 77*9f4ca867SFrançois Tigeot } 78*9f4ca867SFrançois Tigeot 79*9f4ca867SFrançois Tigeot static int 80*9f4ca867SFrançois Tigeot bit_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) 81*9f4ca867SFrançois Tigeot { 82*9f4ca867SFrançois Tigeot /* XXX Linux really does try to transfer some data here */ 83*9f4ca867SFrançois Tigeot return 0; 84*9f4ca867SFrançois Tigeot } 85*9f4ca867SFrançois Tigeot 86*9f4ca867SFrançois Tigeot static uint32_t 87*9f4ca867SFrançois Tigeot bit_func(struct i2c_adapter *adap) 88*9f4ca867SFrançois Tigeot { 89*9f4ca867SFrançois Tigeot return (I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL | 90*9f4ca867SFrançois Tigeot I2C_FUNC_SMBUS_READ_BLOCK_DATA | 91*9f4ca867SFrançois Tigeot I2C_FUNC_SMBUS_BLOCK_PROC_CALL | 92*9f4ca867SFrançois Tigeot I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING); 93*9f4ca867SFrançois Tigeot } 94*9f4ca867SFrançois Tigeot 95*9f4ca867SFrançois Tigeot const struct i2c_algorithm i2c_bit_algo = { 96*9f4ca867SFrançois Tigeot .master_xfer = bit_xfer, 97*9f4ca867SFrançois Tigeot .functionality = bit_func, 98*9f4ca867SFrançois Tigeot }; 99