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], ®s->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, ®s->cr_sr);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* Wait for transfer to complete (TIP = 0) */
138*4882a593Smuzhiyun start_time = jiffies;
139*4882a593Smuzhiyun status = ioread8(®s->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(®s->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, ®s->cr_sr);
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /* Wait for transfer to complete (TIP = 0) */
197*4882a593Smuzhiyun start_time = jiffies;
198*4882a593Smuzhiyun status = ioread8(®s->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(®s->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(®s->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, ®s->cr_sr);
324*4882a593Smuzhiyun iowrite8(0, ®s->ctr);
325*4882a593Smuzhiyun iowrite8(0, ®s->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(®s->cr_sr);
337*4882a593Smuzhiyun } while (status & M00018_SR_BITMAP_TIP_MSK);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /* Disable I2C */
340*4882a593Smuzhiyun iowrite8(0, ®s->ctr);
341*4882a593Smuzhiyun iowrite8(0, ®s->cr_sr);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /* Calculate i2c prescaler */
344*4882a593Smuzhiyun iowrite8(prescale & 0xff, ®s->prerlo);
345*4882a593Smuzhiyun iowrite8((prescale >> 8) & 0xff, ®s->prerhi);
346*4882a593Smuzhiyun /* Enable I2C, interrupts disabled */
347*4882a593Smuzhiyun iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->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