xref: /OK3568_Linux_fs/kernel/drivers/media/pci/cobalt/cobalt-i2c.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  cobalt I2C functions
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Derived from cx18-i2c.c
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
8*4882a593Smuzhiyun  *  All rights reserved.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "cobalt-driver.h"
12*4882a593Smuzhiyun #include "cobalt-i2c.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun struct cobalt_i2c_regs {
15*4882a593Smuzhiyun 	/* Clock prescaler register lo-byte */
16*4882a593Smuzhiyun 	u8 prerlo;
17*4882a593Smuzhiyun 	u8 dummy0[3];
18*4882a593Smuzhiyun 	/* Clock prescaler register high-byte */
19*4882a593Smuzhiyun 	u8 prerhi;
20*4882a593Smuzhiyun 	u8 dummy1[3];
21*4882a593Smuzhiyun 	/* Control register */
22*4882a593Smuzhiyun 	u8 ctr;
23*4882a593Smuzhiyun 	u8 dummy2[3];
24*4882a593Smuzhiyun 	/* Transmit/Receive register */
25*4882a593Smuzhiyun 	u8 txr_rxr;
26*4882a593Smuzhiyun 	u8 dummy3[3];
27*4882a593Smuzhiyun 	/* Command and Status register */
28*4882a593Smuzhiyun 	u8 cr_sr;
29*4882a593Smuzhiyun 	u8 dummy4[3];
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /* CTR[7:0] - Control register */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /* I2C Core enable bit */
35*4882a593Smuzhiyun #define M00018_CTR_BITMAP_EN_MSK	(1 << 7)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /* I2C Core interrupt enable bit */
38*4882a593Smuzhiyun #define M00018_CTR_BITMAP_IEN_MSK	(1 << 6)
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* CR[7:0] - Command register */
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /* I2C start condition */
43*4882a593Smuzhiyun #define M00018_CR_BITMAP_STA_MSK	(1 << 7)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /* I2C stop condition */
46*4882a593Smuzhiyun #define M00018_CR_BITMAP_STO_MSK	(1 << 6)
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /* I2C read from slave */
49*4882a593Smuzhiyun #define M00018_CR_BITMAP_RD_MSK		(1 << 5)
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /* I2C write to slave */
52*4882a593Smuzhiyun #define M00018_CR_BITMAP_WR_MSK		(1 << 4)
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /* I2C ack */
55*4882a593Smuzhiyun #define M00018_CR_BITMAP_ACK_MSK	(1 << 3)
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* I2C Interrupt ack */
58*4882a593Smuzhiyun #define M00018_CR_BITMAP_IACK_MSK	(1 << 0)
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* SR[7:0] - Status register */
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun /* Receive acknowledge from slave */
63*4882a593Smuzhiyun #define M00018_SR_BITMAP_RXACK_MSK	(1 << 7)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* Busy, I2C bus busy (as defined by start / stop bits) */
66*4882a593Smuzhiyun #define M00018_SR_BITMAP_BUSY_MSK	(1 << 6)
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* Arbitration lost - core lost arbitration */
69*4882a593Smuzhiyun #define M00018_SR_BITMAP_AL_MSK		(1 << 5)
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* Transfer in progress */
72*4882a593Smuzhiyun #define M00018_SR_BITMAP_TIP_MSK	(1 << 1)
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* Interrupt flag */
75*4882a593Smuzhiyun #define M00018_SR_BITMAP_IF_MSK		(1 << 0)
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /* Frequency, in Hz */
78*4882a593Smuzhiyun #define I2C_FREQUENCY			400000
79*4882a593Smuzhiyun #define ALT_CPU_FREQ			83333333
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun static struct cobalt_i2c_regs __iomem *
cobalt_i2c_regs(struct cobalt * cobalt,unsigned idx)82*4882a593Smuzhiyun cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	switch (idx) {
85*4882a593Smuzhiyun 	case 0:
86*4882a593Smuzhiyun 	default:
87*4882a593Smuzhiyun 		return (struct cobalt_i2c_regs __iomem *)
88*4882a593Smuzhiyun 			(cobalt->bar1 + COBALT_I2C_0_BASE);
89*4882a593Smuzhiyun 	case 1:
90*4882a593Smuzhiyun 		return (struct cobalt_i2c_regs __iomem *)
91*4882a593Smuzhiyun 			(cobalt->bar1 + COBALT_I2C_1_BASE);
92*4882a593Smuzhiyun 	case 2:
93*4882a593Smuzhiyun 		return (struct cobalt_i2c_regs __iomem *)
94*4882a593Smuzhiyun 			(cobalt->bar1 + COBALT_I2C_2_BASE);
95*4882a593Smuzhiyun 	case 3:
96*4882a593Smuzhiyun 		return (struct cobalt_i2c_regs __iomem *)
97*4882a593Smuzhiyun 			(cobalt->bar1 + COBALT_I2C_3_BASE);
98*4882a593Smuzhiyun 	case 4:
99*4882a593Smuzhiyun 		return (struct cobalt_i2c_regs __iomem *)
100*4882a593Smuzhiyun 			(cobalt->bar1 + COBALT_I2C_HSMA_BASE);
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun /* Do low-level i2c byte transfer.
105*4882a593Smuzhiyun  * Returns -1 in case of an error or 0 otherwise.
106*4882a593Smuzhiyun  */
cobalt_tx_bytes(struct cobalt_i2c_regs __iomem * regs,struct i2c_adapter * adap,bool start,bool stop,u8 * data,u16 len)107*4882a593Smuzhiyun static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs,
108*4882a593Smuzhiyun 		struct i2c_adapter *adap, bool start, bool stop,
109*4882a593Smuzhiyun 		u8 *data, u16 len)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	unsigned long start_time;
112*4882a593Smuzhiyun 	int status;
113*4882a593Smuzhiyun 	int cmd;
114*4882a593Smuzhiyun 	int i;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
117*4882a593Smuzhiyun 		/* Setup data */
118*4882a593Smuzhiyun 		iowrite8(data[i], &regs->txr_rxr);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 		/* Setup command */
121*4882a593Smuzhiyun 		if (i == 0 && start) {
122*4882a593Smuzhiyun 			/* Write + Start */
123*4882a593Smuzhiyun 			cmd = M00018_CR_BITMAP_WR_MSK |
124*4882a593Smuzhiyun 			      M00018_CR_BITMAP_STA_MSK;
125*4882a593Smuzhiyun 		} else if (i == len - 1 && stop) {
126*4882a593Smuzhiyun 			/* Write + Stop */
127*4882a593Smuzhiyun 			cmd = M00018_CR_BITMAP_WR_MSK |
128*4882a593Smuzhiyun 			      M00018_CR_BITMAP_STO_MSK;
129*4882a593Smuzhiyun 		} else {
130*4882a593Smuzhiyun 			/* Write only */
131*4882a593Smuzhiyun 			cmd = M00018_CR_BITMAP_WR_MSK;
132*4882a593Smuzhiyun 		}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 		/* Execute command */
135*4882a593Smuzhiyun 		iowrite8(cmd, &regs->cr_sr);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 		/* Wait for transfer to complete (TIP = 0) */
138*4882a593Smuzhiyun 		start_time = jiffies;
139*4882a593Smuzhiyun 		status = ioread8(&regs->cr_sr);
140*4882a593Smuzhiyun 		while (status & M00018_SR_BITMAP_TIP_MSK) {
141*4882a593Smuzhiyun 			if (time_after(jiffies, start_time + adap->timeout))
142*4882a593Smuzhiyun 				return -ETIMEDOUT;
143*4882a593Smuzhiyun 			cond_resched();
144*4882a593Smuzhiyun 			status = ioread8(&regs->cr_sr);
145*4882a593Smuzhiyun 		}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 		/* Verify ACK */
148*4882a593Smuzhiyun 		if (status & M00018_SR_BITMAP_RXACK_MSK) {
149*4882a593Smuzhiyun 			/* NO ACK! */
150*4882a593Smuzhiyun 			return -EIO;
151*4882a593Smuzhiyun 		}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		/* Verify arbitration */
154*4882a593Smuzhiyun 		if (status & M00018_SR_BITMAP_AL_MSK) {
155*4882a593Smuzhiyun 			/* Arbitration lost! */
156*4882a593Smuzhiyun 			return -EIO;
157*4882a593Smuzhiyun 		}
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 	return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun /* Do low-level i2c byte read.
163*4882a593Smuzhiyun  * Returns -1 in case of an error or 0 otherwise.
164*4882a593Smuzhiyun  */
cobalt_rx_bytes(struct cobalt_i2c_regs __iomem * regs,struct i2c_adapter * adap,bool start,bool stop,u8 * data,u16 len)165*4882a593Smuzhiyun static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs,
166*4882a593Smuzhiyun 		struct i2c_adapter *adap, bool start, bool stop,
167*4882a593Smuzhiyun 		u8 *data, u16 len)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	unsigned long start_time;
170*4882a593Smuzhiyun 	int status;
171*4882a593Smuzhiyun 	int cmd;
172*4882a593Smuzhiyun 	int i;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
175*4882a593Smuzhiyun 		/* Setup command */
176*4882a593Smuzhiyun 		if (i == 0 && start) {
177*4882a593Smuzhiyun 			/* Read + Start */
178*4882a593Smuzhiyun 			cmd = M00018_CR_BITMAP_RD_MSK |
179*4882a593Smuzhiyun 			      M00018_CR_BITMAP_STA_MSK;
180*4882a593Smuzhiyun 		} else if (i == len - 1 && stop) {
181*4882a593Smuzhiyun 			/* Read + Stop */
182*4882a593Smuzhiyun 			cmd = M00018_CR_BITMAP_RD_MSK |
183*4882a593Smuzhiyun 			      M00018_CR_BITMAP_STO_MSK;
184*4882a593Smuzhiyun 		} else {
185*4882a593Smuzhiyun 			/* Read only */
186*4882a593Smuzhiyun 			cmd = M00018_CR_BITMAP_RD_MSK;
187*4882a593Smuzhiyun 		}
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 		/* Last byte to read, no ACK */
190*4882a593Smuzhiyun 		if (i == len - 1)
191*4882a593Smuzhiyun 			cmd |= M00018_CR_BITMAP_ACK_MSK;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 		/* Execute command */
194*4882a593Smuzhiyun 		iowrite8(cmd, &regs->cr_sr);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 		/* Wait for transfer to complete (TIP = 0) */
197*4882a593Smuzhiyun 		start_time = jiffies;
198*4882a593Smuzhiyun 		status = ioread8(&regs->cr_sr);
199*4882a593Smuzhiyun 		while (status & M00018_SR_BITMAP_TIP_MSK) {
200*4882a593Smuzhiyun 			if (time_after(jiffies, start_time + adap->timeout))
201*4882a593Smuzhiyun 				return -ETIMEDOUT;
202*4882a593Smuzhiyun 			cond_resched();
203*4882a593Smuzhiyun 			status = ioread8(&regs->cr_sr);
204*4882a593Smuzhiyun 		}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 		/* Verify arbitration */
207*4882a593Smuzhiyun 		if (status & M00018_SR_BITMAP_AL_MSK) {
208*4882a593Smuzhiyun 			/* Arbitration lost! */
209*4882a593Smuzhiyun 			return -EIO;
210*4882a593Smuzhiyun 		}
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		/* Store data */
213*4882a593Smuzhiyun 		data[i] = ioread8(&regs->txr_rxr);
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 	return 0;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun /* Generate stop condition on i2c bus.
219*4882a593Smuzhiyun  * The m00018 stop isn't doing the right thing (wrong timing).
220*4882a593Smuzhiyun  * So instead send a start condition, 8 zeroes and a stop condition.
221*4882a593Smuzhiyun  */
cobalt_stop(struct cobalt_i2c_regs __iomem * regs,struct i2c_adapter * adap)222*4882a593Smuzhiyun static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs,
223*4882a593Smuzhiyun 		struct i2c_adapter *adap)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun 	u8 data = 0;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	return cobalt_tx_bytes(regs, adap, true, true, &data, 1);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
cobalt_xfer(struct i2c_adapter * adap,struct i2c_msg msgs[],int num)230*4882a593Smuzhiyun static int cobalt_xfer(struct i2c_adapter *adap,
231*4882a593Smuzhiyun 			struct i2c_msg msgs[], int num)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	struct cobalt_i2c_data *data = adap->algo_data;
234*4882a593Smuzhiyun 	struct cobalt_i2c_regs __iomem *regs = data->regs;
235*4882a593Smuzhiyun 	struct i2c_msg *pmsg;
236*4882a593Smuzhiyun 	unsigned short flags;
237*4882a593Smuzhiyun 	int ret = 0;
238*4882a593Smuzhiyun 	int i, j;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
241*4882a593Smuzhiyun 		int stop = (i == num - 1);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 		pmsg = &msgs[i];
244*4882a593Smuzhiyun 		flags = pmsg->flags;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 		if (!(pmsg->flags & I2C_M_NOSTART)) {
247*4882a593Smuzhiyun 			u8 addr = pmsg->addr << 1;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 			if (flags & I2C_M_RD)
250*4882a593Smuzhiyun 				addr |= 1;
251*4882a593Smuzhiyun 			if (flags & I2C_M_REV_DIR_ADDR)
252*4882a593Smuzhiyun 				addr ^= 1;
253*4882a593Smuzhiyun 			for (j = 0; j < adap->retries; j++) {
254*4882a593Smuzhiyun 				ret = cobalt_tx_bytes(regs, adap, true, false,
255*4882a593Smuzhiyun 						      &addr, 1);
256*4882a593Smuzhiyun 				if (!ret)
257*4882a593Smuzhiyun 					break;
258*4882a593Smuzhiyun 				cobalt_stop(regs, adap);
259*4882a593Smuzhiyun 			}
260*4882a593Smuzhiyun 			if (ret < 0)
261*4882a593Smuzhiyun 				return ret;
262*4882a593Smuzhiyun 			ret = 0;
263*4882a593Smuzhiyun 		}
264*4882a593Smuzhiyun 		if (pmsg->flags & I2C_M_RD) {
265*4882a593Smuzhiyun 			/* read bytes into buffer */
266*4882a593Smuzhiyun 			ret = cobalt_rx_bytes(regs, adap, false, stop,
267*4882a593Smuzhiyun 					pmsg->buf, pmsg->len);
268*4882a593Smuzhiyun 			if (ret < 0)
269*4882a593Smuzhiyun 				goto bailout;
270*4882a593Smuzhiyun 		} else {
271*4882a593Smuzhiyun 			/* write bytes from buffer */
272*4882a593Smuzhiyun 			ret = cobalt_tx_bytes(regs, adap, false, stop,
273*4882a593Smuzhiyun 					pmsg->buf, pmsg->len);
274*4882a593Smuzhiyun 			if (ret < 0)
275*4882a593Smuzhiyun 				goto bailout;
276*4882a593Smuzhiyun 		}
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 	ret = i;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun bailout:
281*4882a593Smuzhiyun 	if (ret < 0)
282*4882a593Smuzhiyun 		cobalt_stop(regs, adap);
283*4882a593Smuzhiyun 	return ret;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
cobalt_func(struct i2c_adapter * adap)286*4882a593Smuzhiyun static u32 cobalt_func(struct i2c_adapter *adap)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun /* template for i2c-bit-algo */
292*4882a593Smuzhiyun static const struct i2c_adapter cobalt_i2c_adap_template = {
293*4882a593Smuzhiyun 	.name = "cobalt i2c driver",
294*4882a593Smuzhiyun 	.algo = NULL,                   /* set by i2c-algo-bit */
295*4882a593Smuzhiyun 	.algo_data = NULL,              /* filled from template */
296*4882a593Smuzhiyun 	.owner = THIS_MODULE,
297*4882a593Smuzhiyun };
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun static const struct i2c_algorithm cobalt_algo = {
300*4882a593Smuzhiyun 	.master_xfer	= cobalt_xfer,
301*4882a593Smuzhiyun 	.functionality	= cobalt_func,
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun /* init + register i2c algo-bit adapter */
cobalt_i2c_init(struct cobalt * cobalt)305*4882a593Smuzhiyun int cobalt_i2c_init(struct cobalt *cobalt)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	int i, err;
308*4882a593Smuzhiyun 	int status;
309*4882a593Smuzhiyun 	int prescale;
310*4882a593Smuzhiyun 	unsigned long start_time;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	cobalt_dbg(1, "i2c init\n");
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	/* Define I2C clock prescaler */
315*4882a593Smuzhiyun 	prescale = ((ALT_CPU_FREQ) / (5 * I2C_FREQUENCY)) - 1;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
318*4882a593Smuzhiyun 		struct cobalt_i2c_regs __iomem *regs =
319*4882a593Smuzhiyun 			cobalt_i2c_regs(cobalt, i);
320*4882a593Smuzhiyun 		struct i2c_adapter *adap = &cobalt->i2c_adap[i];
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 		/* Disable I2C */
323*4882a593Smuzhiyun 		iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->cr_sr);
324*4882a593Smuzhiyun 		iowrite8(0, &regs->ctr);
325*4882a593Smuzhiyun 		iowrite8(0, &regs->cr_sr);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		start_time = jiffies;
328*4882a593Smuzhiyun 		do {
329*4882a593Smuzhiyun 			if (time_after(jiffies, start_time + HZ)) {
330*4882a593Smuzhiyun 				if (cobalt_ignore_err) {
331*4882a593Smuzhiyun 					adap->dev.parent = NULL;
332*4882a593Smuzhiyun 					return 0;
333*4882a593Smuzhiyun 				}
334*4882a593Smuzhiyun 				return -ETIMEDOUT;
335*4882a593Smuzhiyun 			}
336*4882a593Smuzhiyun 			status = ioread8(&regs->cr_sr);
337*4882a593Smuzhiyun 		} while (status & M00018_SR_BITMAP_TIP_MSK);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 		/* Disable I2C */
340*4882a593Smuzhiyun 		iowrite8(0, &regs->ctr);
341*4882a593Smuzhiyun 		iowrite8(0, &regs->cr_sr);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 		/* Calculate i2c prescaler */
344*4882a593Smuzhiyun 		iowrite8(prescale & 0xff, &regs->prerlo);
345*4882a593Smuzhiyun 		iowrite8((prescale >> 8) & 0xff, &regs->prerhi);
346*4882a593Smuzhiyun 		/* Enable I2C, interrupts disabled */
347*4882a593Smuzhiyun 		iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->ctr);
348*4882a593Smuzhiyun 		/* Setup algorithm for adapter */
349*4882a593Smuzhiyun 		cobalt->i2c_data[i].cobalt = cobalt;
350*4882a593Smuzhiyun 		cobalt->i2c_data[i].regs = regs;
351*4882a593Smuzhiyun 		*adap = cobalt_i2c_adap_template;
352*4882a593Smuzhiyun 		adap->algo = &cobalt_algo;
353*4882a593Smuzhiyun 		adap->algo_data = &cobalt->i2c_data[i];
354*4882a593Smuzhiyun 		adap->retries = 3;
355*4882a593Smuzhiyun 		sprintf(adap->name + strlen(adap->name),
356*4882a593Smuzhiyun 				" #%d-%d", cobalt->instance, i);
357*4882a593Smuzhiyun 		i2c_set_adapdata(adap, &cobalt->v4l2_dev);
358*4882a593Smuzhiyun 		adap->dev.parent = &cobalt->pci_dev->dev;
359*4882a593Smuzhiyun 		err = i2c_add_adapter(adap);
360*4882a593Smuzhiyun 		if (err) {
361*4882a593Smuzhiyun 			if (cobalt_ignore_err) {
362*4882a593Smuzhiyun 				adap->dev.parent = NULL;
363*4882a593Smuzhiyun 				return 0;
364*4882a593Smuzhiyun 			}
365*4882a593Smuzhiyun 			while (i--)
366*4882a593Smuzhiyun 				i2c_del_adapter(&cobalt->i2c_adap[i]);
367*4882a593Smuzhiyun 			return err;
368*4882a593Smuzhiyun 		}
369*4882a593Smuzhiyun 		cobalt_info("registered bus %s\n", adap->name);
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun 	return 0;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun 
cobalt_i2c_exit(struct cobalt * cobalt)374*4882a593Smuzhiyun void cobalt_i2c_exit(struct cobalt *cobalt)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	int i;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	cobalt_dbg(1, "i2c exit\n");
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
381*4882a593Smuzhiyun 		cobalt_err("unregistered bus %s\n", cobalt->i2c_adap[i].name);
382*4882a593Smuzhiyun 		i2c_del_adapter(&cobalt->i2c_adap[i]);
383*4882a593Smuzhiyun 	}
384*4882a593Smuzhiyun }
385