16884db3cSHans Verkuil // SPDX-License-Identifier: GPL-2.0-only
285756a06SHans Verkuil /*
385756a06SHans Verkuil  *  cobalt I2C functions
485756a06SHans Verkuil  *
585756a06SHans Verkuil  *  Derived from cx18-i2c.c
685756a06SHans Verkuil  *
785756a06SHans Verkuil  *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
885756a06SHans Verkuil  *  All rights reserved.
985756a06SHans Verkuil  */
1085756a06SHans Verkuil 
1185756a06SHans Verkuil #include "cobalt-driver.h"
1285756a06SHans Verkuil #include "cobalt-i2c.h"
1385756a06SHans Verkuil 
1485756a06SHans Verkuil struct cobalt_i2c_regs {
1585756a06SHans Verkuil 	/* Clock prescaler register lo-byte */
1685756a06SHans Verkuil 	u8 prerlo;
1785756a06SHans Verkuil 	u8 dummy0[3];
1885756a06SHans Verkuil 	/* Clock prescaler register high-byte */
1985756a06SHans Verkuil 	u8 prerhi;
2085756a06SHans Verkuil 	u8 dummy1[3];
2185756a06SHans Verkuil 	/* Control register */
2285756a06SHans Verkuil 	u8 ctr;
2385756a06SHans Verkuil 	u8 dummy2[3];
2485756a06SHans Verkuil 	/* Transmit/Receive register */
2585756a06SHans Verkuil 	u8 txr_rxr;
2685756a06SHans Verkuil 	u8 dummy3[3];
2785756a06SHans Verkuil 	/* Command and Status register */
2885756a06SHans Verkuil 	u8 cr_sr;
2985756a06SHans Verkuil 	u8 dummy4[3];
3085756a06SHans Verkuil };
3185756a06SHans Verkuil 
3285756a06SHans Verkuil /* CTR[7:0] - Control register */
3385756a06SHans Verkuil 
3485756a06SHans Verkuil /* I2C Core enable bit */
3585756a06SHans Verkuil #define M00018_CTR_BITMAP_EN_MSK	(1 << 7)
3685756a06SHans Verkuil 
3785756a06SHans Verkuil /* I2C Core interrupt enable bit */
3885756a06SHans Verkuil #define M00018_CTR_BITMAP_IEN_MSK	(1 << 6)
3985756a06SHans Verkuil 
4085756a06SHans Verkuil /* CR[7:0] - Command register */
4185756a06SHans Verkuil 
4285756a06SHans Verkuil /* I2C start condition */
4385756a06SHans Verkuil #define M00018_CR_BITMAP_STA_MSK	(1 << 7)
4485756a06SHans Verkuil 
4585756a06SHans Verkuil /* I2C stop condition */
4685756a06SHans Verkuil #define M00018_CR_BITMAP_STO_MSK	(1 << 6)
4785756a06SHans Verkuil 
4885756a06SHans Verkuil /* I2C read from slave */
4985756a06SHans Verkuil #define M00018_CR_BITMAP_RD_MSK		(1 << 5)
5085756a06SHans Verkuil 
5185756a06SHans Verkuil /* I2C write to slave */
5285756a06SHans Verkuil #define M00018_CR_BITMAP_WR_MSK		(1 << 4)
5385756a06SHans Verkuil 
5485756a06SHans Verkuil /* I2C ack */
5585756a06SHans Verkuil #define M00018_CR_BITMAP_ACK_MSK	(1 << 3)
5685756a06SHans Verkuil 
5785756a06SHans Verkuil /* I2C Interrupt ack */
5885756a06SHans Verkuil #define M00018_CR_BITMAP_IACK_MSK	(1 << 0)
5985756a06SHans Verkuil 
6085756a06SHans Verkuil /* SR[7:0] - Status register */
6185756a06SHans Verkuil 
6285756a06SHans Verkuil /* Receive acknowledge from slave */
6385756a06SHans Verkuil #define M00018_SR_BITMAP_RXACK_MSK	(1 << 7)
6485756a06SHans Verkuil 
6585756a06SHans Verkuil /* Busy, I2C bus busy (as defined by start / stop bits) */
6685756a06SHans Verkuil #define M00018_SR_BITMAP_BUSY_MSK	(1 << 6)
6785756a06SHans Verkuil 
6885756a06SHans Verkuil /* Arbitration lost - core lost arbitration */
6985756a06SHans Verkuil #define M00018_SR_BITMAP_AL_MSK		(1 << 5)
7085756a06SHans Verkuil 
7185756a06SHans Verkuil /* Transfer in progress */
7285756a06SHans Verkuil #define M00018_SR_BITMAP_TIP_MSK	(1 << 1)
7385756a06SHans Verkuil 
7485756a06SHans Verkuil /* Interrupt flag */
7585756a06SHans Verkuil #define M00018_SR_BITMAP_IF_MSK		(1 << 0)
7685756a06SHans Verkuil 
7785756a06SHans Verkuil /* Frequency, in Hz */
7885756a06SHans Verkuil #define I2C_FREQUENCY			400000
7985756a06SHans Verkuil #define ALT_CPU_FREQ			83333333
8085756a06SHans Verkuil 
810664fb61SHans Verkuil static struct cobalt_i2c_regs __iomem *
cobalt_i2c_regs(struct cobalt * cobalt,unsigned idx)8285756a06SHans Verkuil cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx)
8385756a06SHans Verkuil {
8485756a06SHans Verkuil 	switch (idx) {
8585756a06SHans Verkuil 	case 0:
8685756a06SHans Verkuil 	default:
870664fb61SHans Verkuil 		return (struct cobalt_i2c_regs __iomem *)
8885756a06SHans Verkuil 			(cobalt->bar1 + COBALT_I2C_0_BASE);
8985756a06SHans Verkuil 	case 1:
900664fb61SHans Verkuil 		return (struct cobalt_i2c_regs __iomem *)
9185756a06SHans Verkuil 			(cobalt->bar1 + COBALT_I2C_1_BASE);
9285756a06SHans Verkuil 	case 2:
930664fb61SHans Verkuil 		return (struct cobalt_i2c_regs __iomem *)
9485756a06SHans Verkuil 			(cobalt->bar1 + COBALT_I2C_2_BASE);
9585756a06SHans Verkuil 	case 3:
960664fb61SHans Verkuil 		return (struct cobalt_i2c_regs __iomem *)
9785756a06SHans Verkuil 			(cobalt->bar1 + COBALT_I2C_3_BASE);
9885756a06SHans Verkuil 	case 4:
990664fb61SHans Verkuil 		return (struct cobalt_i2c_regs __iomem *)
10085756a06SHans Verkuil 			(cobalt->bar1 + COBALT_I2C_HSMA_BASE);
10185756a06SHans Verkuil 	}
10285756a06SHans Verkuil }
10385756a06SHans Verkuil 
10485756a06SHans Verkuil /* Do low-level i2c byte transfer.
10585756a06SHans Verkuil  * Returns -1 in case of an error or 0 otherwise.
10685756a06SHans Verkuil  */
cobalt_tx_bytes(struct cobalt_i2c_regs __iomem * regs,struct i2c_adapter * adap,bool start,bool stop,u8 * data,u16 len)1070664fb61SHans Verkuil static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs,
10885756a06SHans Verkuil 		struct i2c_adapter *adap, bool start, bool stop,
10985756a06SHans Verkuil 		u8 *data, u16 len)
11085756a06SHans Verkuil {
11185756a06SHans Verkuil 	unsigned long start_time;
11285756a06SHans Verkuil 	int status;
11385756a06SHans Verkuil 	int cmd;
11485756a06SHans Verkuil 	int i;
11585756a06SHans Verkuil 
11685756a06SHans Verkuil 	for (i = 0; i < len; i++) {
11785756a06SHans Verkuil 		/* Setup data */
1180664fb61SHans Verkuil 		iowrite8(data[i], &regs->txr_rxr);
11985756a06SHans Verkuil 
12085756a06SHans Verkuil 		/* Setup command */
1217f988187SDaniel W. S. Almeida 		if (i == 0 && start) {
12285756a06SHans Verkuil 			/* Write + Start */
12385756a06SHans Verkuil 			cmd = M00018_CR_BITMAP_WR_MSK |
12485756a06SHans Verkuil 			      M00018_CR_BITMAP_STA_MSK;
1257f988187SDaniel W. S. Almeida 		} else if (i == len - 1 && stop) {
12685756a06SHans Verkuil 			/* Write + Stop */
12785756a06SHans Verkuil 			cmd = M00018_CR_BITMAP_WR_MSK |
12885756a06SHans Verkuil 			      M00018_CR_BITMAP_STO_MSK;
12985756a06SHans Verkuil 		} else {
13085756a06SHans Verkuil 			/* Write only */
13185756a06SHans Verkuil 			cmd = M00018_CR_BITMAP_WR_MSK;
13285756a06SHans Verkuil 		}
13385756a06SHans Verkuil 
13485756a06SHans Verkuil 		/* Execute command */
1350664fb61SHans Verkuil 		iowrite8(cmd, &regs->cr_sr);
13685756a06SHans Verkuil 
13785756a06SHans Verkuil 		/* Wait for transfer to complete (TIP = 0) */
13885756a06SHans Verkuil 		start_time = jiffies;
1390664fb61SHans Verkuil 		status = ioread8(&regs->cr_sr);
14085756a06SHans Verkuil 		while (status & M00018_SR_BITMAP_TIP_MSK) {
14185756a06SHans Verkuil 			if (time_after(jiffies, start_time + adap->timeout))
14285756a06SHans Verkuil 				return -ETIMEDOUT;
14385756a06SHans Verkuil 			cond_resched();
1440664fb61SHans Verkuil 			status = ioread8(&regs->cr_sr);
14585756a06SHans Verkuil 		}
14685756a06SHans Verkuil 
14785756a06SHans Verkuil 		/* Verify ACK */
14885756a06SHans Verkuil 		if (status & M00018_SR_BITMAP_RXACK_MSK) {
14985756a06SHans Verkuil 			/* NO ACK! */
15085756a06SHans Verkuil 			return -EIO;
15185756a06SHans Verkuil 		}
15285756a06SHans Verkuil 
15385756a06SHans Verkuil 		/* Verify arbitration */
15485756a06SHans Verkuil 		if (status & M00018_SR_BITMAP_AL_MSK) {
15585756a06SHans Verkuil 			/* Arbitration lost! */
15685756a06SHans Verkuil 			return -EIO;
15785756a06SHans Verkuil 		}
15885756a06SHans Verkuil 	}
15985756a06SHans Verkuil 	return 0;
16085756a06SHans Verkuil }
16185756a06SHans Verkuil 
16285756a06SHans Verkuil /* Do low-level i2c byte read.
16385756a06SHans Verkuil  * Returns -1 in case of an error or 0 otherwise.
16485756a06SHans Verkuil  */
cobalt_rx_bytes(struct cobalt_i2c_regs __iomem * regs,struct i2c_adapter * adap,bool start,bool stop,u8 * data,u16 len)1650664fb61SHans Verkuil static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs,
16685756a06SHans Verkuil 		struct i2c_adapter *adap, bool start, bool stop,
16785756a06SHans Verkuil 		u8 *data, u16 len)
16885756a06SHans Verkuil {
16985756a06SHans Verkuil 	unsigned long start_time;
17085756a06SHans Verkuil 	int status;
17185756a06SHans Verkuil 	int cmd;
17285756a06SHans Verkuil 	int i;
17385756a06SHans Verkuil 
17485756a06SHans Verkuil 	for (i = 0; i < len; i++) {
17585756a06SHans Verkuil 		/* Setup command */
1767f988187SDaniel W. S. Almeida 		if (i == 0 && start) {
17785756a06SHans Verkuil 			/* Read + Start */
17885756a06SHans Verkuil 			cmd = M00018_CR_BITMAP_RD_MSK |
17985756a06SHans Verkuil 			      M00018_CR_BITMAP_STA_MSK;
1807f988187SDaniel W. S. Almeida 		} else if (i == len - 1 && stop) {
18185756a06SHans Verkuil 			/* Read + Stop */
18285756a06SHans Verkuil 			cmd = M00018_CR_BITMAP_RD_MSK |
18385756a06SHans Verkuil 			      M00018_CR_BITMAP_STO_MSK;
18485756a06SHans Verkuil 		} else {
18585756a06SHans Verkuil 			/* Read only */
18685756a06SHans Verkuil 			cmd = M00018_CR_BITMAP_RD_MSK;
18785756a06SHans Verkuil 		}
18885756a06SHans Verkuil 
18985756a06SHans Verkuil 		/* Last byte to read, no ACK */
19085756a06SHans Verkuil 		if (i == len - 1)
19185756a06SHans Verkuil 			cmd |= M00018_CR_BITMAP_ACK_MSK;
19285756a06SHans Verkuil 
19385756a06SHans Verkuil 		/* Execute command */
1940664fb61SHans Verkuil 		iowrite8(cmd, &regs->cr_sr);
19585756a06SHans Verkuil 
19685756a06SHans Verkuil 		/* Wait for transfer to complete (TIP = 0) */
19785756a06SHans Verkuil 		start_time = jiffies;
1980664fb61SHans Verkuil 		status = ioread8(&regs->cr_sr);
19985756a06SHans Verkuil 		while (status & M00018_SR_BITMAP_TIP_MSK) {
20085756a06SHans Verkuil 			if (time_after(jiffies, start_time + adap->timeout))
20185756a06SHans Verkuil 				return -ETIMEDOUT;
20285756a06SHans Verkuil 			cond_resched();
2030664fb61SHans Verkuil 			status = ioread8(&regs->cr_sr);
20485756a06SHans Verkuil 		}
20585756a06SHans Verkuil 
20685756a06SHans Verkuil 		/* Verify arbitration */
20785756a06SHans Verkuil 		if (status & M00018_SR_BITMAP_AL_MSK) {
20885756a06SHans Verkuil 			/* Arbitration lost! */
20985756a06SHans Verkuil 			return -EIO;
21085756a06SHans Verkuil 		}
21185756a06SHans Verkuil 
21285756a06SHans Verkuil 		/* Store data */
2130664fb61SHans Verkuil 		data[i] = ioread8(&regs->txr_rxr);
21485756a06SHans Verkuil 	}
21585756a06SHans Verkuil 	return 0;
21685756a06SHans Verkuil }
21785756a06SHans Verkuil 
21885756a06SHans Verkuil /* Generate stop condition on i2c bus.
21985756a06SHans Verkuil  * The m00018 stop isn't doing the right thing (wrong timing).
22085756a06SHans Verkuil  * So instead send a start condition, 8 zeroes and a stop condition.
22185756a06SHans Verkuil  */
cobalt_stop(struct cobalt_i2c_regs __iomem * regs,struct i2c_adapter * adap)2220664fb61SHans Verkuil static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs,
22385756a06SHans Verkuil 		struct i2c_adapter *adap)
22485756a06SHans Verkuil {
22585756a06SHans Verkuil 	u8 data = 0;
22685756a06SHans Verkuil 
22785756a06SHans Verkuil 	return cobalt_tx_bytes(regs, adap, true, true, &data, 1);
22885756a06SHans Verkuil }
22985756a06SHans Verkuil 
cobalt_xfer(struct i2c_adapter * adap,struct i2c_msg msgs[],int num)23085756a06SHans Verkuil static int cobalt_xfer(struct i2c_adapter *adap,
23185756a06SHans Verkuil 			struct i2c_msg msgs[], int num)
23285756a06SHans Verkuil {
23385756a06SHans Verkuil 	struct cobalt_i2c_data *data = adap->algo_data;
2340664fb61SHans Verkuil 	struct cobalt_i2c_regs __iomem *regs = data->regs;
23585756a06SHans Verkuil 	struct i2c_msg *pmsg;
23685756a06SHans Verkuil 	unsigned short flags;
23785756a06SHans Verkuil 	int ret = 0;
23885756a06SHans Verkuil 	int i, j;
23985756a06SHans Verkuil 
24085756a06SHans Verkuil 	for (i = 0; i < num; i++) {
24185756a06SHans Verkuil 		int stop = (i == num - 1);
24285756a06SHans Verkuil 
24385756a06SHans Verkuil 		pmsg = &msgs[i];
24485756a06SHans Verkuil 		flags = pmsg->flags;
24585756a06SHans Verkuil 
24685756a06SHans Verkuil 		if (!(pmsg->flags & I2C_M_NOSTART)) {
24785756a06SHans Verkuil 			u8 addr = pmsg->addr << 1;
24885756a06SHans Verkuil 
24985756a06SHans Verkuil 			if (flags & I2C_M_RD)
25085756a06SHans Verkuil 				addr |= 1;
25185756a06SHans Verkuil 			if (flags & I2C_M_REV_DIR_ADDR)
25285756a06SHans Verkuil 				addr ^= 1;
25385756a06SHans Verkuil 			for (j = 0; j < adap->retries; j++) {
25485756a06SHans Verkuil 				ret = cobalt_tx_bytes(regs, adap, true, false,
25585756a06SHans Verkuil 						      &addr, 1);
25685756a06SHans Verkuil 				if (!ret)
25785756a06SHans Verkuil 					break;
25885756a06SHans Verkuil 				cobalt_stop(regs, adap);
25985756a06SHans Verkuil 			}
26085756a06SHans Verkuil 			if (ret < 0)
26185756a06SHans Verkuil 				return ret;
26285756a06SHans Verkuil 			ret = 0;
26385756a06SHans Verkuil 		}
26485756a06SHans Verkuil 		if (pmsg->flags & I2C_M_RD) {
26585756a06SHans Verkuil 			/* read bytes into buffer */
26685756a06SHans Verkuil 			ret = cobalt_rx_bytes(regs, adap, false, stop,
26785756a06SHans Verkuil 					pmsg->buf, pmsg->len);
26885756a06SHans Verkuil 			if (ret < 0)
26985756a06SHans Verkuil 				goto bailout;
27085756a06SHans Verkuil 		} else {
27185756a06SHans Verkuil 			/* write bytes from buffer */
27285756a06SHans Verkuil 			ret = cobalt_tx_bytes(regs, adap, false, stop,
27385756a06SHans Verkuil 					pmsg->buf, pmsg->len);
27485756a06SHans Verkuil 			if (ret < 0)
27585756a06SHans Verkuil 				goto bailout;
27685756a06SHans Verkuil 		}
27785756a06SHans Verkuil 	}
27885756a06SHans Verkuil 	ret = i;
27985756a06SHans Verkuil 
28085756a06SHans Verkuil bailout:
28185756a06SHans Verkuil 	if (ret < 0)
28285756a06SHans Verkuil 		cobalt_stop(regs, adap);
28385756a06SHans Verkuil 	return ret;
28485756a06SHans Verkuil }
28585756a06SHans Verkuil 
cobalt_func(struct i2c_adapter * adap)28685756a06SHans Verkuil static u32 cobalt_func(struct i2c_adapter *adap)
28785756a06SHans Verkuil {
28885756a06SHans Verkuil 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
28985756a06SHans Verkuil }
29085756a06SHans Verkuil 
29185756a06SHans Verkuil /* template for i2c-bit-algo */
292e5fffebeSBhumika Goyal static const struct i2c_adapter cobalt_i2c_adap_template = {
29385756a06SHans Verkuil 	.name = "cobalt i2c driver",
29485756a06SHans Verkuil 	.algo = NULL,                   /* set by i2c-algo-bit */
29585756a06SHans Verkuil 	.algo_data = NULL,              /* filled from template */
29685756a06SHans Verkuil 	.owner = THIS_MODULE,
29785756a06SHans Verkuil };
29885756a06SHans Verkuil 
29985756a06SHans Verkuil static const struct i2c_algorithm cobalt_algo = {
30085756a06SHans Verkuil 	.master_xfer	= cobalt_xfer,
30185756a06SHans Verkuil 	.functionality	= cobalt_func,
30285756a06SHans Verkuil };
30385756a06SHans Verkuil 
30485756a06SHans Verkuil /* init + register i2c algo-bit adapter */
cobalt_i2c_init(struct cobalt * cobalt)30585756a06SHans Verkuil int cobalt_i2c_init(struct cobalt *cobalt)
30685756a06SHans Verkuil {
30785756a06SHans Verkuil 	int i, err;
30885756a06SHans Verkuil 	int status;
30985756a06SHans Verkuil 	int prescale;
31085756a06SHans Verkuil 	unsigned long start_time;
31185756a06SHans Verkuil 
31285756a06SHans Verkuil 	cobalt_dbg(1, "i2c init\n");
31385756a06SHans Verkuil 
31485756a06SHans Verkuil 	/* Define I2C clock prescaler */
31585756a06SHans Verkuil 	prescale = ((ALT_CPU_FREQ) / (5 * I2C_FREQUENCY)) - 1;
31685756a06SHans Verkuil 
31785756a06SHans Verkuil 	for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
3180664fb61SHans Verkuil 		struct cobalt_i2c_regs __iomem *regs =
31985756a06SHans Verkuil 			cobalt_i2c_regs(cobalt, i);
32085756a06SHans Verkuil 		struct i2c_adapter *adap = &cobalt->i2c_adap[i];
32185756a06SHans Verkuil 
32285756a06SHans Verkuil 		/* Disable I2C */
3230664fb61SHans Verkuil 		iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->cr_sr);
3240664fb61SHans Verkuil 		iowrite8(0, &regs->ctr);
3250664fb61SHans Verkuil 		iowrite8(0, &regs->cr_sr);
32685756a06SHans Verkuil 
32785756a06SHans Verkuil 		start_time = jiffies;
32885756a06SHans Verkuil 		do {
32985756a06SHans Verkuil 			if (time_after(jiffies, start_time + HZ)) {
33085756a06SHans Verkuil 				if (cobalt_ignore_err) {
33185756a06SHans Verkuil 					adap->dev.parent = NULL;
33285756a06SHans Verkuil 					return 0;
33385756a06SHans Verkuil 				}
33485756a06SHans Verkuil 				return -ETIMEDOUT;
33585756a06SHans Verkuil 			}
3360664fb61SHans Verkuil 			status = ioread8(&regs->cr_sr);
33785756a06SHans Verkuil 		} while (status & M00018_SR_BITMAP_TIP_MSK);
33885756a06SHans Verkuil 
33985756a06SHans Verkuil 		/* Disable I2C */
3400664fb61SHans Verkuil 		iowrite8(0, &regs->ctr);
3410664fb61SHans Verkuil 		iowrite8(0, &regs->cr_sr);
34285756a06SHans Verkuil 
34385756a06SHans Verkuil 		/* Calculate i2c prescaler */
3440664fb61SHans Verkuil 		iowrite8(prescale & 0xff, &regs->prerlo);
3450664fb61SHans Verkuil 		iowrite8((prescale >> 8) & 0xff, &regs->prerhi);
34685756a06SHans Verkuil 		/* Enable I2C, interrupts disabled */
3470664fb61SHans Verkuil 		iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->ctr);
34885756a06SHans Verkuil 		/* Setup algorithm for adapter */
34985756a06SHans Verkuil 		cobalt->i2c_data[i].cobalt = cobalt;
35085756a06SHans Verkuil 		cobalt->i2c_data[i].regs = regs;
35185756a06SHans Verkuil 		*adap = cobalt_i2c_adap_template;
35285756a06SHans Verkuil 		adap->algo = &cobalt_algo;
35385756a06SHans Verkuil 		adap->algo_data = &cobalt->i2c_data[i];
35485756a06SHans Verkuil 		adap->retries = 3;
35585756a06SHans Verkuil 		sprintf(adap->name + strlen(adap->name),
35685756a06SHans Verkuil 				" #%d-%d", cobalt->instance, i);
35785756a06SHans Verkuil 		i2c_set_adapdata(adap, &cobalt->v4l2_dev);
35885756a06SHans Verkuil 		adap->dev.parent = &cobalt->pci_dev->dev;
35985756a06SHans Verkuil 		err = i2c_add_adapter(adap);
36085756a06SHans Verkuil 		if (err) {
36185756a06SHans Verkuil 			if (cobalt_ignore_err) {
36285756a06SHans Verkuil 				adap->dev.parent = NULL;
36385756a06SHans Verkuil 				return 0;
36485756a06SHans Verkuil 			}
36585756a06SHans Verkuil 			while (i--)
36685756a06SHans Verkuil 				i2c_del_adapter(&cobalt->i2c_adap[i]);
36785756a06SHans Verkuil 			return err;
36885756a06SHans Verkuil 		}
36985756a06SHans Verkuil 		cobalt_info("registered bus %s\n", adap->name);
37085756a06SHans Verkuil 	}
37185756a06SHans Verkuil 	return 0;
37285756a06SHans Verkuil }
37385756a06SHans Verkuil 
cobalt_i2c_exit(struct cobalt * cobalt)37485756a06SHans Verkuil void cobalt_i2c_exit(struct cobalt *cobalt)
37585756a06SHans Verkuil {
37685756a06SHans Verkuil 	int i;
37785756a06SHans Verkuil 
37885756a06SHans Verkuil 	cobalt_dbg(1, "i2c exit\n");
37985756a06SHans Verkuil 
38085756a06SHans Verkuil 	for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
38185756a06SHans Verkuil 		cobalt_err("unregistered bus %s\n", cobalt->i2c_adap[i].name);
38285756a06SHans Verkuil 		i2c_del_adapter(&cobalt->i2c_adap[i]);
38385756a06SHans Verkuil 	}
38485756a06SHans Verkuil }
385