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