185756a06SHans Verkuil /* 285756a06SHans Verkuil * cobalt I2C functions 385756a06SHans Verkuil * 485756a06SHans Verkuil * Derived from cx18-i2c.c 585756a06SHans Verkuil * 685756a06SHans Verkuil * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates. 785756a06SHans Verkuil * All rights reserved. 885756a06SHans Verkuil * 985756a06SHans Verkuil * This program is free software; you may redistribute it and/or modify 1085756a06SHans Verkuil * it under the terms of the GNU General Public License as published by 1185756a06SHans Verkuil * the Free Software Foundation; version 2 of the License. 1285756a06SHans Verkuil * 1385756a06SHans Verkuil * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1485756a06SHans Verkuil * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1585756a06SHans Verkuil * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1685756a06SHans Verkuil * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1785756a06SHans Verkuil * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1885756a06SHans Verkuil * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1985756a06SHans Verkuil * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2085756a06SHans Verkuil * SOFTWARE. 2185756a06SHans Verkuil */ 2285756a06SHans Verkuil 2385756a06SHans Verkuil #include "cobalt-driver.h" 2485756a06SHans Verkuil #include "cobalt-i2c.h" 2585756a06SHans Verkuil 2685756a06SHans Verkuil struct cobalt_i2c_regs { 2785756a06SHans Verkuil /* Clock prescaler register lo-byte */ 2885756a06SHans Verkuil u8 prerlo; 2985756a06SHans Verkuil u8 dummy0[3]; 3085756a06SHans Verkuil /* Clock prescaler register high-byte */ 3185756a06SHans Verkuil u8 prerhi; 3285756a06SHans Verkuil u8 dummy1[3]; 3385756a06SHans Verkuil /* Control register */ 3485756a06SHans Verkuil u8 ctr; 3585756a06SHans Verkuil u8 dummy2[3]; 3685756a06SHans Verkuil /* Transmit/Receive register */ 3785756a06SHans Verkuil u8 txr_rxr; 3885756a06SHans Verkuil u8 dummy3[3]; 3985756a06SHans Verkuil /* Command and Status register */ 4085756a06SHans Verkuil u8 cr_sr; 4185756a06SHans Verkuil u8 dummy4[3]; 4285756a06SHans Verkuil }; 4385756a06SHans Verkuil 4485756a06SHans Verkuil /* CTR[7:0] - Control register */ 4585756a06SHans Verkuil 4685756a06SHans Verkuil /* I2C Core enable bit */ 4785756a06SHans Verkuil #define M00018_CTR_BITMAP_EN_MSK (1 << 7) 4885756a06SHans Verkuil 4985756a06SHans Verkuil /* I2C Core interrupt enable bit */ 5085756a06SHans Verkuil #define M00018_CTR_BITMAP_IEN_MSK (1 << 6) 5185756a06SHans Verkuil 5285756a06SHans Verkuil /* CR[7:0] - Command register */ 5385756a06SHans Verkuil 5485756a06SHans Verkuil /* I2C start condition */ 5585756a06SHans Verkuil #define M00018_CR_BITMAP_STA_MSK (1 << 7) 5685756a06SHans Verkuil 5785756a06SHans Verkuil /* I2C stop condition */ 5885756a06SHans Verkuil #define M00018_CR_BITMAP_STO_MSK (1 << 6) 5985756a06SHans Verkuil 6085756a06SHans Verkuil /* I2C read from slave */ 6185756a06SHans Verkuil #define M00018_CR_BITMAP_RD_MSK (1 << 5) 6285756a06SHans Verkuil 6385756a06SHans Verkuil /* I2C write to slave */ 6485756a06SHans Verkuil #define M00018_CR_BITMAP_WR_MSK (1 << 4) 6585756a06SHans Verkuil 6685756a06SHans Verkuil /* I2C ack */ 6785756a06SHans Verkuil #define M00018_CR_BITMAP_ACK_MSK (1 << 3) 6885756a06SHans Verkuil 6985756a06SHans Verkuil /* I2C Interrupt ack */ 7085756a06SHans Verkuil #define M00018_CR_BITMAP_IACK_MSK (1 << 0) 7185756a06SHans Verkuil 7285756a06SHans Verkuil /* SR[7:0] - Status register */ 7385756a06SHans Verkuil 7485756a06SHans Verkuil /* Receive acknowledge from slave */ 7585756a06SHans Verkuil #define M00018_SR_BITMAP_RXACK_MSK (1 << 7) 7685756a06SHans Verkuil 7785756a06SHans Verkuil /* Busy, I2C bus busy (as defined by start / stop bits) */ 7885756a06SHans Verkuil #define M00018_SR_BITMAP_BUSY_MSK (1 << 6) 7985756a06SHans Verkuil 8085756a06SHans Verkuil /* Arbitration lost - core lost arbitration */ 8185756a06SHans Verkuil #define M00018_SR_BITMAP_AL_MSK (1 << 5) 8285756a06SHans Verkuil 8385756a06SHans Verkuil /* Transfer in progress */ 8485756a06SHans Verkuil #define M00018_SR_BITMAP_TIP_MSK (1 << 1) 8585756a06SHans Verkuil 8685756a06SHans Verkuil /* Interrupt flag */ 8785756a06SHans Verkuil #define M00018_SR_BITMAP_IF_MSK (1 << 0) 8885756a06SHans Verkuil 8985756a06SHans Verkuil /* Frequency, in Hz */ 9085756a06SHans Verkuil #define I2C_FREQUENCY 400000 9185756a06SHans Verkuil #define ALT_CPU_FREQ 83333333 9285756a06SHans Verkuil 930664fb61SHans Verkuil static struct cobalt_i2c_regs __iomem * 9485756a06SHans Verkuil cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx) 9585756a06SHans Verkuil { 9685756a06SHans Verkuil switch (idx) { 9785756a06SHans Verkuil case 0: 9885756a06SHans Verkuil default: 990664fb61SHans Verkuil return (struct cobalt_i2c_regs __iomem *) 10085756a06SHans Verkuil (cobalt->bar1 + COBALT_I2C_0_BASE); 10185756a06SHans Verkuil case 1: 1020664fb61SHans Verkuil return (struct cobalt_i2c_regs __iomem *) 10385756a06SHans Verkuil (cobalt->bar1 + COBALT_I2C_1_BASE); 10485756a06SHans Verkuil case 2: 1050664fb61SHans Verkuil return (struct cobalt_i2c_regs __iomem *) 10685756a06SHans Verkuil (cobalt->bar1 + COBALT_I2C_2_BASE); 10785756a06SHans Verkuil case 3: 1080664fb61SHans Verkuil return (struct cobalt_i2c_regs __iomem *) 10985756a06SHans Verkuil (cobalt->bar1 + COBALT_I2C_3_BASE); 11085756a06SHans Verkuil case 4: 1110664fb61SHans Verkuil return (struct cobalt_i2c_regs __iomem *) 11285756a06SHans Verkuil (cobalt->bar1 + COBALT_I2C_HSMA_BASE); 11385756a06SHans Verkuil } 11485756a06SHans Verkuil } 11585756a06SHans Verkuil 11685756a06SHans Verkuil /* Do low-level i2c byte transfer. 11785756a06SHans Verkuil * Returns -1 in case of an error or 0 otherwise. 11885756a06SHans Verkuil */ 1190664fb61SHans Verkuil static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs, 12085756a06SHans Verkuil struct i2c_adapter *adap, bool start, bool stop, 12185756a06SHans Verkuil u8 *data, u16 len) 12285756a06SHans Verkuil { 12385756a06SHans Verkuil unsigned long start_time; 12485756a06SHans Verkuil int status; 12585756a06SHans Verkuil int cmd; 12685756a06SHans Verkuil int i; 12785756a06SHans Verkuil 12885756a06SHans Verkuil for (i = 0; i < len; i++) { 12985756a06SHans Verkuil /* Setup data */ 1300664fb61SHans Verkuil iowrite8(data[i], ®s->txr_rxr); 13185756a06SHans Verkuil 13285756a06SHans Verkuil /* Setup command */ 13385756a06SHans Verkuil if (i == 0 && start != 0) { 13485756a06SHans Verkuil /* Write + Start */ 13585756a06SHans Verkuil cmd = M00018_CR_BITMAP_WR_MSK | 13685756a06SHans Verkuil M00018_CR_BITMAP_STA_MSK; 13785756a06SHans Verkuil } else if (i == len - 1 && stop != 0) { 13885756a06SHans Verkuil /* Write + Stop */ 13985756a06SHans Verkuil cmd = M00018_CR_BITMAP_WR_MSK | 14085756a06SHans Verkuil M00018_CR_BITMAP_STO_MSK; 14185756a06SHans Verkuil } else { 14285756a06SHans Verkuil /* Write only */ 14385756a06SHans Verkuil cmd = M00018_CR_BITMAP_WR_MSK; 14485756a06SHans Verkuil } 14585756a06SHans Verkuil 14685756a06SHans Verkuil /* Execute command */ 1470664fb61SHans Verkuil iowrite8(cmd, ®s->cr_sr); 14885756a06SHans Verkuil 14985756a06SHans Verkuil /* Wait for transfer to complete (TIP = 0) */ 15085756a06SHans Verkuil start_time = jiffies; 1510664fb61SHans Verkuil status = ioread8(®s->cr_sr); 15285756a06SHans Verkuil while (status & M00018_SR_BITMAP_TIP_MSK) { 15385756a06SHans Verkuil if (time_after(jiffies, start_time + adap->timeout)) 15485756a06SHans Verkuil return -ETIMEDOUT; 15585756a06SHans Verkuil cond_resched(); 1560664fb61SHans Verkuil status = ioread8(®s->cr_sr); 15785756a06SHans Verkuil } 15885756a06SHans Verkuil 15985756a06SHans Verkuil /* Verify ACK */ 16085756a06SHans Verkuil if (status & M00018_SR_BITMAP_RXACK_MSK) { 16185756a06SHans Verkuil /* NO ACK! */ 16285756a06SHans Verkuil return -EIO; 16385756a06SHans Verkuil } 16485756a06SHans Verkuil 16585756a06SHans Verkuil /* Verify arbitration */ 16685756a06SHans Verkuil if (status & M00018_SR_BITMAP_AL_MSK) { 16785756a06SHans Verkuil /* Arbitration lost! */ 16885756a06SHans Verkuil return -EIO; 16985756a06SHans Verkuil } 17085756a06SHans Verkuil } 17185756a06SHans Verkuil return 0; 17285756a06SHans Verkuil } 17385756a06SHans Verkuil 17485756a06SHans Verkuil /* Do low-level i2c byte read. 17585756a06SHans Verkuil * Returns -1 in case of an error or 0 otherwise. 17685756a06SHans Verkuil */ 1770664fb61SHans Verkuil static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs, 17885756a06SHans Verkuil struct i2c_adapter *adap, bool start, bool stop, 17985756a06SHans Verkuil u8 *data, u16 len) 18085756a06SHans Verkuil { 18185756a06SHans Verkuil unsigned long start_time; 18285756a06SHans Verkuil int status; 18385756a06SHans Verkuil int cmd; 18485756a06SHans Verkuil int i; 18585756a06SHans Verkuil 18685756a06SHans Verkuil for (i = 0; i < len; i++) { 18785756a06SHans Verkuil /* Setup command */ 18885756a06SHans Verkuil if (i == 0 && start != 0) { 18985756a06SHans Verkuil /* Read + Start */ 19085756a06SHans Verkuil cmd = M00018_CR_BITMAP_RD_MSK | 19185756a06SHans Verkuil M00018_CR_BITMAP_STA_MSK; 19285756a06SHans Verkuil } else if (i == len - 1 && stop != 0) { 19385756a06SHans Verkuil /* Read + Stop */ 19485756a06SHans Verkuil cmd = M00018_CR_BITMAP_RD_MSK | 19585756a06SHans Verkuil M00018_CR_BITMAP_STO_MSK; 19685756a06SHans Verkuil } else { 19785756a06SHans Verkuil /* Read only */ 19885756a06SHans Verkuil cmd = M00018_CR_BITMAP_RD_MSK; 19985756a06SHans Verkuil } 20085756a06SHans Verkuil 20185756a06SHans Verkuil /* Last byte to read, no ACK */ 20285756a06SHans Verkuil if (i == len - 1) 20385756a06SHans Verkuil cmd |= M00018_CR_BITMAP_ACK_MSK; 20485756a06SHans Verkuil 20585756a06SHans Verkuil /* Execute command */ 2060664fb61SHans Verkuil iowrite8(cmd, ®s->cr_sr); 20785756a06SHans Verkuil 20885756a06SHans Verkuil /* Wait for transfer to complete (TIP = 0) */ 20985756a06SHans Verkuil start_time = jiffies; 2100664fb61SHans Verkuil status = ioread8(®s->cr_sr); 21185756a06SHans Verkuil while (status & M00018_SR_BITMAP_TIP_MSK) { 21285756a06SHans Verkuil if (time_after(jiffies, start_time + adap->timeout)) 21385756a06SHans Verkuil return -ETIMEDOUT; 21485756a06SHans Verkuil cond_resched(); 2150664fb61SHans Verkuil status = ioread8(®s->cr_sr); 21685756a06SHans Verkuil } 21785756a06SHans Verkuil 21885756a06SHans Verkuil /* Verify arbitration */ 21985756a06SHans Verkuil if (status & M00018_SR_BITMAP_AL_MSK) { 22085756a06SHans Verkuil /* Arbitration lost! */ 22185756a06SHans Verkuil return -EIO; 22285756a06SHans Verkuil } 22385756a06SHans Verkuil 22485756a06SHans Verkuil /* Store data */ 2250664fb61SHans Verkuil data[i] = ioread8(®s->txr_rxr); 22685756a06SHans Verkuil } 22785756a06SHans Verkuil return 0; 22885756a06SHans Verkuil } 22985756a06SHans Verkuil 23085756a06SHans Verkuil /* Generate stop condition on i2c bus. 23185756a06SHans Verkuil * The m00018 stop isn't doing the right thing (wrong timing). 23285756a06SHans Verkuil * So instead send a start condition, 8 zeroes and a stop condition. 23385756a06SHans Verkuil */ 2340664fb61SHans Verkuil static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs, 23585756a06SHans Verkuil struct i2c_adapter *adap) 23685756a06SHans Verkuil { 23785756a06SHans Verkuil u8 data = 0; 23885756a06SHans Verkuil 23985756a06SHans Verkuil return cobalt_tx_bytes(regs, adap, true, true, &data, 1); 24085756a06SHans Verkuil } 24185756a06SHans Verkuil 24285756a06SHans Verkuil static int cobalt_xfer(struct i2c_adapter *adap, 24385756a06SHans Verkuil struct i2c_msg msgs[], int num) 24485756a06SHans Verkuil { 24585756a06SHans Verkuil struct cobalt_i2c_data *data = adap->algo_data; 2460664fb61SHans Verkuil struct cobalt_i2c_regs __iomem *regs = data->regs; 24785756a06SHans Verkuil struct i2c_msg *pmsg; 24885756a06SHans Verkuil unsigned short flags; 24985756a06SHans Verkuil int ret = 0; 25085756a06SHans Verkuil int i, j; 25185756a06SHans Verkuil 25285756a06SHans Verkuil for (i = 0; i < num; i++) { 25385756a06SHans Verkuil int stop = (i == num - 1); 25485756a06SHans Verkuil 25585756a06SHans Verkuil pmsg = &msgs[i]; 25685756a06SHans Verkuil flags = pmsg->flags; 25785756a06SHans Verkuil 25885756a06SHans Verkuil if (!(pmsg->flags & I2C_M_NOSTART)) { 25985756a06SHans Verkuil u8 addr = pmsg->addr << 1; 26085756a06SHans Verkuil 26185756a06SHans Verkuil if (flags & I2C_M_RD) 26285756a06SHans Verkuil addr |= 1; 26385756a06SHans Verkuil if (flags & I2C_M_REV_DIR_ADDR) 26485756a06SHans Verkuil addr ^= 1; 26585756a06SHans Verkuil for (j = 0; j < adap->retries; j++) { 26685756a06SHans Verkuil ret = cobalt_tx_bytes(regs, adap, true, false, 26785756a06SHans Verkuil &addr, 1); 26885756a06SHans Verkuil if (!ret) 26985756a06SHans Verkuil break; 27085756a06SHans Verkuil cobalt_stop(regs, adap); 27185756a06SHans Verkuil } 27285756a06SHans Verkuil if (ret < 0) 27385756a06SHans Verkuil return ret; 27485756a06SHans Verkuil ret = 0; 27585756a06SHans Verkuil } 27685756a06SHans Verkuil if (pmsg->flags & I2C_M_RD) { 27785756a06SHans Verkuil /* read bytes into buffer */ 27885756a06SHans Verkuil ret = cobalt_rx_bytes(regs, adap, false, stop, 27985756a06SHans Verkuil pmsg->buf, pmsg->len); 28085756a06SHans Verkuil if (ret < 0) 28185756a06SHans Verkuil goto bailout; 28285756a06SHans Verkuil } else { 28385756a06SHans Verkuil /* write bytes from buffer */ 28485756a06SHans Verkuil ret = cobalt_tx_bytes(regs, adap, false, stop, 28585756a06SHans Verkuil pmsg->buf, pmsg->len); 28685756a06SHans Verkuil if (ret < 0) 28785756a06SHans Verkuil goto bailout; 28885756a06SHans Verkuil } 28985756a06SHans Verkuil } 29085756a06SHans Verkuil ret = i; 29185756a06SHans Verkuil 29285756a06SHans Verkuil bailout: 29385756a06SHans Verkuil if (ret < 0) 29485756a06SHans Verkuil cobalt_stop(regs, adap); 29585756a06SHans Verkuil return ret; 29685756a06SHans Verkuil } 29785756a06SHans Verkuil 29885756a06SHans Verkuil static u32 cobalt_func(struct i2c_adapter *adap) 29985756a06SHans Verkuil { 30085756a06SHans Verkuil return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 30185756a06SHans Verkuil } 30285756a06SHans Verkuil 30385756a06SHans Verkuil /* template for i2c-bit-algo */ 30485756a06SHans Verkuil static struct i2c_adapter cobalt_i2c_adap_template = { 30585756a06SHans Verkuil .name = "cobalt i2c driver", 30685756a06SHans Verkuil .algo = NULL, /* set by i2c-algo-bit */ 30785756a06SHans Verkuil .algo_data = NULL, /* filled from template */ 30885756a06SHans Verkuil .owner = THIS_MODULE, 30985756a06SHans Verkuil }; 31085756a06SHans Verkuil 31185756a06SHans Verkuil static const struct i2c_algorithm cobalt_algo = { 31285756a06SHans Verkuil .master_xfer = cobalt_xfer, 31385756a06SHans Verkuil .functionality = cobalt_func, 31485756a06SHans Verkuil }; 31585756a06SHans Verkuil 31685756a06SHans Verkuil /* init + register i2c algo-bit adapter */ 31785756a06SHans Verkuil int cobalt_i2c_init(struct cobalt *cobalt) 31885756a06SHans Verkuil { 31985756a06SHans Verkuil int i, err; 32085756a06SHans Verkuil int status; 32185756a06SHans Verkuil int prescale; 32285756a06SHans Verkuil unsigned long start_time; 32385756a06SHans Verkuil 32485756a06SHans Verkuil cobalt_dbg(1, "i2c init\n"); 32585756a06SHans Verkuil 32685756a06SHans Verkuil /* Define I2C clock prescaler */ 32785756a06SHans Verkuil prescale = ((ALT_CPU_FREQ) / (5 * I2C_FREQUENCY)) - 1; 32885756a06SHans Verkuil 32985756a06SHans Verkuil for (i = 0; i < COBALT_NUM_ADAPTERS; i++) { 3300664fb61SHans Verkuil struct cobalt_i2c_regs __iomem *regs = 33185756a06SHans Verkuil cobalt_i2c_regs(cobalt, i); 33285756a06SHans Verkuil struct i2c_adapter *adap = &cobalt->i2c_adap[i]; 33385756a06SHans Verkuil 33485756a06SHans Verkuil /* Disable I2C */ 3350664fb61SHans Verkuil iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->cr_sr); 3360664fb61SHans Verkuil iowrite8(0, ®s->ctr); 3370664fb61SHans Verkuil iowrite8(0, ®s->cr_sr); 33885756a06SHans Verkuil 33985756a06SHans Verkuil start_time = jiffies; 34085756a06SHans Verkuil do { 34185756a06SHans Verkuil if (time_after(jiffies, start_time + HZ)) { 34285756a06SHans Verkuil if (cobalt_ignore_err) { 34385756a06SHans Verkuil adap->dev.parent = NULL; 34485756a06SHans Verkuil return 0; 34585756a06SHans Verkuil } 34685756a06SHans Verkuil return -ETIMEDOUT; 34785756a06SHans Verkuil } 3480664fb61SHans Verkuil status = ioread8(®s->cr_sr); 34985756a06SHans Verkuil } while (status & M00018_SR_BITMAP_TIP_MSK); 35085756a06SHans Verkuil 35185756a06SHans Verkuil /* Disable I2C */ 3520664fb61SHans Verkuil iowrite8(0, ®s->ctr); 3530664fb61SHans Verkuil iowrite8(0, ®s->cr_sr); 35485756a06SHans Verkuil 35585756a06SHans Verkuil /* Calculate i2c prescaler */ 3560664fb61SHans Verkuil iowrite8(prescale & 0xff, ®s->prerlo); 3570664fb61SHans Verkuil iowrite8((prescale >> 8) & 0xff, ®s->prerhi); 35885756a06SHans Verkuil /* Enable I2C, interrupts disabled */ 3590664fb61SHans Verkuil iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->ctr); 36085756a06SHans Verkuil /* Setup algorithm for adapter */ 36185756a06SHans Verkuil cobalt->i2c_data[i].cobalt = cobalt; 36285756a06SHans Verkuil cobalt->i2c_data[i].regs = regs; 36385756a06SHans Verkuil *adap = cobalt_i2c_adap_template; 36485756a06SHans Verkuil adap->algo = &cobalt_algo; 36585756a06SHans Verkuil adap->algo_data = &cobalt->i2c_data[i]; 36685756a06SHans Verkuil adap->retries = 3; 36785756a06SHans Verkuil sprintf(adap->name + strlen(adap->name), 36885756a06SHans Verkuil " #%d-%d", cobalt->instance, i); 36985756a06SHans Verkuil i2c_set_adapdata(adap, &cobalt->v4l2_dev); 37085756a06SHans Verkuil adap->dev.parent = &cobalt->pci_dev->dev; 37185756a06SHans Verkuil err = i2c_add_adapter(adap); 37285756a06SHans Verkuil if (err) { 37385756a06SHans Verkuil if (cobalt_ignore_err) { 37485756a06SHans Verkuil adap->dev.parent = NULL; 37585756a06SHans Verkuil return 0; 37685756a06SHans Verkuil } 37785756a06SHans Verkuil while (i--) 37885756a06SHans Verkuil i2c_del_adapter(&cobalt->i2c_adap[i]); 37985756a06SHans Verkuil return err; 38085756a06SHans Verkuil } 38185756a06SHans Verkuil cobalt_info("registered bus %s\n", adap->name); 38285756a06SHans Verkuil } 38385756a06SHans Verkuil return 0; 38485756a06SHans Verkuil } 38585756a06SHans Verkuil 38685756a06SHans Verkuil void cobalt_i2c_exit(struct cobalt *cobalt) 38785756a06SHans Verkuil { 38885756a06SHans Verkuil int i; 38985756a06SHans Verkuil 39085756a06SHans Verkuil cobalt_dbg(1, "i2c exit\n"); 39185756a06SHans Verkuil 39285756a06SHans Verkuil for (i = 0; i < COBALT_NUM_ADAPTERS; i++) { 39385756a06SHans Verkuil cobalt_err("unregistered bus %s\n", cobalt->i2c_adap[i].name); 39485756a06SHans Verkuil i2c_del_adapter(&cobalt->i2c_adap[i]); 39585756a06SHans Verkuil } 39685756a06SHans Verkuil } 397