blob: ad16b89b8d0ce44f1e76795047da2451184eb66b [file] [log] [blame]
Hans Verkuil85756a02015-05-12 08:52:21 -03001/*
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
26struct 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
Hans Verkuil0664fb62015-05-22 05:51:39 -030093static struct cobalt_i2c_regs __iomem *
Hans Verkuil85756a02015-05-12 08:52:21 -030094cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx)
95{
96 switch (idx) {
97 case 0:
98 default:
Hans Verkuil0664fb62015-05-22 05:51:39 -030099 return (struct cobalt_i2c_regs __iomem *)
Hans Verkuil85756a02015-05-12 08:52:21 -0300100 (cobalt->bar1 + COBALT_I2C_0_BASE);
101 case 1:
Hans Verkuil0664fb62015-05-22 05:51:39 -0300102 return (struct cobalt_i2c_regs __iomem *)
Hans Verkuil85756a02015-05-12 08:52:21 -0300103 (cobalt->bar1 + COBALT_I2C_1_BASE);
104 case 2:
Hans Verkuil0664fb62015-05-22 05:51:39 -0300105 return (struct cobalt_i2c_regs __iomem *)
Hans Verkuil85756a02015-05-12 08:52:21 -0300106 (cobalt->bar1 + COBALT_I2C_2_BASE);
107 case 3:
Hans Verkuil0664fb62015-05-22 05:51:39 -0300108 return (struct cobalt_i2c_regs __iomem *)
Hans Verkuil85756a02015-05-12 08:52:21 -0300109 (cobalt->bar1 + COBALT_I2C_3_BASE);
110 case 4:
Hans Verkuil0664fb62015-05-22 05:51:39 -0300111 return (struct cobalt_i2c_regs __iomem *)
Hans Verkuil85756a02015-05-12 08:52:21 -0300112 (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 */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300119static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs,
Hans Verkuil85756a02015-05-12 08:52:21 -0300120 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 */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300130 iowrite8(data[i], &regs->txr_rxr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300131
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 */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300147 iowrite8(cmd, &regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300148
149 /* Wait for transfer to complete (TIP = 0) */
150 start_time = jiffies;
Hans Verkuil0664fb62015-05-22 05:51:39 -0300151 status = ioread8(&regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300152 while (status & M00018_SR_BITMAP_TIP_MSK) {
153 if (time_after(jiffies, start_time + adap->timeout))
154 return -ETIMEDOUT;
155 cond_resched();
Hans Verkuil0664fb62015-05-22 05:51:39 -0300156 status = ioread8(&regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300157 }
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 */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300177static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs,
Hans Verkuil85756a02015-05-12 08:52:21 -0300178 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 */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300206 iowrite8(cmd, &regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300207
208 /* Wait for transfer to complete (TIP = 0) */
209 start_time = jiffies;
Hans Verkuil0664fb62015-05-22 05:51:39 -0300210 status = ioread8(&regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300211 while (status & M00018_SR_BITMAP_TIP_MSK) {
212 if (time_after(jiffies, start_time + adap->timeout))
213 return -ETIMEDOUT;
214 cond_resched();
Hans Verkuil0664fb62015-05-22 05:51:39 -0300215 status = ioread8(&regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300216 }
217
218 /* Verify arbitration */
219 if (status & M00018_SR_BITMAP_AL_MSK) {
220 /* Arbitration lost! */
221 return -EIO;
222 }
223
224 /* Store data */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300225 data[i] = ioread8(&regs->txr_rxr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300226 }
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 */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300234static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs,
Hans Verkuil85756a02015-05-12 08:52:21 -0300235 struct i2c_adapter *adap)
236{
237 u8 data = 0;
238
239 return cobalt_tx_bytes(regs, adap, true, true, &data, 1);
240}
241
242static int cobalt_xfer(struct i2c_adapter *adap,
243 struct i2c_msg msgs[], int num)
244{
245 struct cobalt_i2c_data *data = adap->algo_data;
Hans Verkuil0664fb62015-05-22 05:51:39 -0300246 struct cobalt_i2c_regs __iomem *regs = data->regs;
Hans Verkuil85756a02015-05-12 08:52:21 -0300247 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
292bailout:
293 if (ret < 0)
294 cobalt_stop(regs, adap);
295 return ret;
296}
297
298static 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 */
304static 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
311static const struct i2c_algorithm cobalt_algo = {
312 .master_xfer = cobalt_xfer,
313 .functionality = cobalt_func,
314};
315
316/* init + register i2c algo-bit adapter */
317int 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++) {
Hans Verkuil0664fb62015-05-22 05:51:39 -0300330 struct cobalt_i2c_regs __iomem *regs =
Hans Verkuil85756a02015-05-12 08:52:21 -0300331 cobalt_i2c_regs(cobalt, i);
332 struct i2c_adapter *adap = &cobalt->i2c_adap[i];
333
334 /* Disable I2C */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300335 iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->cr_sr);
336 iowrite8(0, &regs->ctr);
337 iowrite8(0, &regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300338
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 }
Hans Verkuil0664fb62015-05-22 05:51:39 -0300348 status = ioread8(&regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300349 } while (status & M00018_SR_BITMAP_TIP_MSK);
350
351 /* Disable I2C */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300352 iowrite8(0, &regs->ctr);
353 iowrite8(0, &regs->cr_sr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300354
355 /* Calculate i2c prescaler */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300356 iowrite8(prescale & 0xff, &regs->prerlo);
357 iowrite8((prescale >> 8) & 0xff, &regs->prerhi);
Hans Verkuil85756a02015-05-12 08:52:21 -0300358 /* Enable I2C, interrupts disabled */
Hans Verkuil0664fb62015-05-22 05:51:39 -0300359 iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->ctr);
Hans Verkuil85756a02015-05-12 08:52:21 -0300360 /* 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
386void 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}