4 * Derived from cx18-i2c.c
6 * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
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.
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
23 #include "cobalt-driver.h"
24 #include "cobalt-i2c.h"
26 struct cobalt_i2c_regs
{
27 /* Clock prescaler register lo-byte */
30 /* Clock prescaler register high-byte */
33 /* Control register */
36 /* Transmit/Receive register */
39 /* Command and Status register */
44 /* CTR[7:0] - Control register */
46 /* I2C Core enable bit */
47 #define M00018_CTR_BITMAP_EN_MSK (1 << 7)
49 /* I2C Core interrupt enable bit */
50 #define M00018_CTR_BITMAP_IEN_MSK (1 << 6)
52 /* CR[7:0] - Command register */
54 /* I2C start condition */
55 #define M00018_CR_BITMAP_STA_MSK (1 << 7)
57 /* I2C stop condition */
58 #define M00018_CR_BITMAP_STO_MSK (1 << 6)
60 /* I2C read from slave */
61 #define M00018_CR_BITMAP_RD_MSK (1 << 5)
63 /* I2C write to slave */
64 #define M00018_CR_BITMAP_WR_MSK (1 << 4)
67 #define M00018_CR_BITMAP_ACK_MSK (1 << 3)
69 /* I2C Interrupt ack */
70 #define M00018_CR_BITMAP_IACK_MSK (1 << 0)
72 /* SR[7:0] - Status register */
74 /* Receive acknowledge from slave */
75 #define M00018_SR_BITMAP_RXACK_MSK (1 << 7)
77 /* Busy, I2C bus busy (as defined by start / stop bits) */
78 #define M00018_SR_BITMAP_BUSY_MSK (1 << 6)
80 /* Arbitration lost - core lost arbitration */
81 #define M00018_SR_BITMAP_AL_MSK (1 << 5)
83 /* Transfer in progress */
84 #define M00018_SR_BITMAP_TIP_MSK (1 << 1)
87 #define M00018_SR_BITMAP_IF_MSK (1 << 0)
89 /* Frequency, in Hz */
90 #define I2C_FREQUENCY 400000
91 #define ALT_CPU_FREQ 83333333
93 static struct cobalt_i2c_regs __iomem
*
94 cobalt_i2c_regs(struct cobalt
*cobalt
, unsigned idx
)
99 return (struct cobalt_i2c_regs __iomem
*)
100 (cobalt
->bar1
+ COBALT_I2C_0_BASE
);
102 return (struct cobalt_i2c_regs __iomem
*)
103 (cobalt
->bar1
+ COBALT_I2C_1_BASE
);
105 return (struct cobalt_i2c_regs __iomem
*)
106 (cobalt
->bar1
+ COBALT_I2C_2_BASE
);
108 return (struct cobalt_i2c_regs __iomem
*)
109 (cobalt
->bar1
+ COBALT_I2C_3_BASE
);
111 return (struct cobalt_i2c_regs __iomem
*)
112 (cobalt
->bar1
+ COBALT_I2C_HSMA_BASE
);
116 /* Do low-level i2c byte transfer.
117 * Returns -1 in case of an error or 0 otherwise.
119 static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem
*regs
,
120 struct i2c_adapter
*adap
, bool start
, bool stop
,
123 unsigned long start_time
;
128 for (i
= 0; i
< len
; i
++) {
130 iowrite8(data
[i
], ®s
->txr_rxr
);
133 if (i
== 0 && start
!= 0) {
135 cmd
= M00018_CR_BITMAP_WR_MSK
|
136 M00018_CR_BITMAP_STA_MSK
;
137 } else if (i
== len
- 1 && stop
!= 0) {
139 cmd
= M00018_CR_BITMAP_WR_MSK
|
140 M00018_CR_BITMAP_STO_MSK
;
143 cmd
= M00018_CR_BITMAP_WR_MSK
;
146 /* Execute command */
147 iowrite8(cmd
, ®s
->cr_sr
);
149 /* Wait for transfer to complete (TIP = 0) */
150 start_time
= jiffies
;
151 status
= ioread8(®s
->cr_sr
);
152 while (status
& M00018_SR_BITMAP_TIP_MSK
) {
153 if (time_after(jiffies
, start_time
+ adap
->timeout
))
156 status
= ioread8(®s
->cr_sr
);
160 if (status
& M00018_SR_BITMAP_RXACK_MSK
) {
165 /* Verify arbitration */
166 if (status
& M00018_SR_BITMAP_AL_MSK
) {
167 /* Arbitration lost! */
174 /* Do low-level i2c byte read.
175 * Returns -1 in case of an error or 0 otherwise.
177 static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem
*regs
,
178 struct i2c_adapter
*adap
, bool start
, bool stop
,
181 unsigned long start_time
;
186 for (i
= 0; i
< len
; i
++) {
188 if (i
== 0 && start
!= 0) {
190 cmd
= M00018_CR_BITMAP_RD_MSK
|
191 M00018_CR_BITMAP_STA_MSK
;
192 } else if (i
== len
- 1 && stop
!= 0) {
194 cmd
= M00018_CR_BITMAP_RD_MSK
|
195 M00018_CR_BITMAP_STO_MSK
;
198 cmd
= M00018_CR_BITMAP_RD_MSK
;
201 /* Last byte to read, no ACK */
203 cmd
|= M00018_CR_BITMAP_ACK_MSK
;
205 /* Execute command */
206 iowrite8(cmd
, ®s
->cr_sr
);
208 /* Wait for transfer to complete (TIP = 0) */
209 start_time
= jiffies
;
210 status
= ioread8(®s
->cr_sr
);
211 while (status
& M00018_SR_BITMAP_TIP_MSK
) {
212 if (time_after(jiffies
, start_time
+ adap
->timeout
))
215 status
= ioread8(®s
->cr_sr
);
218 /* Verify arbitration */
219 if (status
& M00018_SR_BITMAP_AL_MSK
) {
220 /* Arbitration lost! */
225 data
[i
] = ioread8(®s
->txr_rxr
);
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.
234 static int cobalt_stop(struct cobalt_i2c_regs __iomem
*regs
,
235 struct i2c_adapter
*adap
)
239 return cobalt_tx_bytes(regs
, adap
, true, true, &data
, 1);
242 static int cobalt_xfer(struct i2c_adapter
*adap
,
243 struct i2c_msg msgs
[], int num
)
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
;
252 for (i
= 0; i
< num
; i
++) {
253 int stop
= (i
== num
- 1);
258 if (!(pmsg
->flags
& I2C_M_NOSTART
)) {
259 u8 addr
= pmsg
->addr
<< 1;
261 if (flags
& I2C_M_RD
)
263 if (flags
& I2C_M_REV_DIR_ADDR
)
265 for (j
= 0; j
< adap
->retries
; j
++) {
266 ret
= cobalt_tx_bytes(regs
, adap
, true, false,
270 cobalt_stop(regs
, adap
);
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
);
283 /* write bytes from buffer */
284 ret
= cobalt_tx_bytes(regs
, adap
, false, stop
,
285 pmsg
->buf
, pmsg
->len
);
294 cobalt_stop(regs
, adap
);
298 static u32
cobalt_func(struct i2c_adapter
*adap
)
300 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
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
,
311 static const struct i2c_algorithm cobalt_algo
= {
312 .master_xfer
= cobalt_xfer
,
313 .functionality
= cobalt_func
,
316 /* init + register i2c algo-bit adapter */
317 int cobalt_i2c_init(struct cobalt
*cobalt
)
322 unsigned long start_time
;
324 cobalt_dbg(1, "i2c init\n");
326 /* Define I2C clock prescaler */
327 prescale
= ((ALT_CPU_FREQ
) / (5 * I2C_FREQUENCY
)) - 1;
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
];
335 iowrite8(M00018_CTR_BITMAP_EN_MSK
, ®s
->cr_sr
);
336 iowrite8(0, ®s
->ctr
);
337 iowrite8(0, ®s
->cr_sr
);
339 start_time
= jiffies
;
341 if (time_after(jiffies
, start_time
+ HZ
)) {
342 if (cobalt_ignore_err
) {
343 adap
->dev
.parent
= NULL
;
348 status
= ioread8(®s
->cr_sr
);
349 } while (status
& M00018_SR_BITMAP_TIP_MSK
);
352 iowrite8(0, ®s
->ctr
);
353 iowrite8(0, ®s
->cr_sr
);
355 /* Calculate i2c prescaler */
356 iowrite8(prescale
& 0xff, ®s
->prerlo
);
357 iowrite8((prescale
>> 8) & 0xff, ®s
->prerhi
);
358 /* Enable I2C, interrupts disabled */
359 iowrite8(M00018_CTR_BITMAP_EN_MSK
, ®s
->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
];
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
);
373 if (cobalt_ignore_err
) {
374 adap
->dev
.parent
= NULL
;
378 i2c_del_adapter(&cobalt
->i2c_adap
[i
]);
381 cobalt_info("registered bus %s\n", adap
->name
);
386 void cobalt_i2c_exit(struct cobalt
*cobalt
)
390 cobalt_dbg(1, "i2c exit\n");
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
]);