aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c193
1 files changed, 182 insertions, 11 deletions
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 9cc361d19941..2404c4e0f35c 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -55,6 +55,32 @@
55#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 55#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8
56#define MV64XXX_I2C_STATUS_NO_STATUS 0xf8 56#define MV64XXX_I2C_STATUS_NO_STATUS 0xf8
57 57
58/* Register defines (I2C bridge) */
59#define MV64XXX_I2C_REG_TX_DATA_LO 0xc0
60#define MV64XXX_I2C_REG_TX_DATA_HI 0xc4
61#define MV64XXX_I2C_REG_RX_DATA_LO 0xc8
62#define MV64XXX_I2C_REG_RX_DATA_HI 0xcc
63#define MV64XXX_I2C_REG_BRIDGE_CONTROL 0xd0
64#define MV64XXX_I2C_REG_BRIDGE_STATUS 0xd4
65#define MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xd8
66#define MV64XXX_I2C_REG_BRIDGE_INTR_MASK 0xdC
67#define MV64XXX_I2C_REG_BRIDGE_TIMING 0xe0
68
69/* Bridge Control values */
70#define MV64XXX_I2C_BRIDGE_CONTROL_WR 0x00000001
71#define MV64XXX_I2C_BRIDGE_CONTROL_RD 0x00000002
72#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2
73#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x00001000
74#define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT 13
75#define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT 16
76#define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x00080000
77
78/* Bridge Status values */
79#define MV64XXX_I2C_BRIDGE_STATUS_ERROR 0x00000001
80#define MV64XXX_I2C_STATUS_OFFLOAD_ERROR 0xf0000001
81#define MV64XXX_I2C_STATUS_OFFLOAD_OK 0xf0000000
82
83
58/* Driver states */ 84/* Driver states */
59enum { 85enum {
60 MV64XXX_I2C_STATE_INVALID, 86 MV64XXX_I2C_STATE_INVALID,
@@ -71,14 +97,17 @@ enum {
71enum { 97enum {
72 MV64XXX_I2C_ACTION_INVALID, 98 MV64XXX_I2C_ACTION_INVALID,
73 MV64XXX_I2C_ACTION_CONTINUE, 99 MV64XXX_I2C_ACTION_CONTINUE,
100 MV64XXX_I2C_ACTION_OFFLOAD_SEND_START,
74 MV64XXX_I2C_ACTION_SEND_START, 101 MV64XXX_I2C_ACTION_SEND_START,
75 MV64XXX_I2C_ACTION_SEND_RESTART, 102 MV64XXX_I2C_ACTION_SEND_RESTART,
103 MV64XXX_I2C_ACTION_OFFLOAD_RESTART,
76 MV64XXX_I2C_ACTION_SEND_ADDR_1, 104 MV64XXX_I2C_ACTION_SEND_ADDR_1,
77 MV64XXX_I2C_ACTION_SEND_ADDR_2, 105 MV64XXX_I2C_ACTION_SEND_ADDR_2,
78 MV64XXX_I2C_ACTION_SEND_DATA, 106 MV64XXX_I2C_ACTION_SEND_DATA,
79 MV64XXX_I2C_ACTION_RCV_DATA, 107 MV64XXX_I2C_ACTION_RCV_DATA,
80 MV64XXX_I2C_ACTION_RCV_DATA_STOP, 108 MV64XXX_I2C_ACTION_RCV_DATA_STOP,
81 MV64XXX_I2C_ACTION_SEND_STOP, 109 MV64XXX_I2C_ACTION_SEND_STOP,
110 MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP,
82}; 111};
83 112
84struct mv64xxx_i2c_regs { 113struct mv64xxx_i2c_regs {
@@ -117,6 +146,7 @@ struct mv64xxx_i2c_data {
117 spinlock_t lock; 146 spinlock_t lock;
118 struct i2c_msg *msg; 147 struct i2c_msg *msg;
119 struct i2c_adapter adapter; 148 struct i2c_adapter adapter;
149 bool offload_enabled;
120}; 150};
121 151
122static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { 152static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
@@ -165,6 +195,77 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
165 } 195 }
166} 196}
167 197
198static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data)
199{
200 unsigned long data_reg_hi = 0;
201 unsigned long data_reg_lo = 0;
202 unsigned long ctrl_reg;
203 struct i2c_msg *msg = drv_data->msgs;
204
205 drv_data->msg = msg;
206 drv_data->byte_posn = 0;
207 drv_data->bytes_left = msg->len;
208 drv_data->aborting = 0;
209 drv_data->rc = 0;
210 /* Only regular transactions can be offloaded */
211 if ((msg->flags & ~(I2C_M_TEN | I2C_M_RD)) != 0)
212 return -EINVAL;
213
214 /* Only 1-8 byte transfers can be offloaded */
215 if (msg->len < 1 || msg->len > 8)
216 return -EINVAL;
217
218 /* Build transaction */
219 ctrl_reg = MV64XXX_I2C_BRIDGE_CONTROL_ENABLE |
220 (msg->addr << MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT);
221
222 if ((msg->flags & I2C_M_TEN) != 0)
223 ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT;
224
225 if ((msg->flags & I2C_M_RD) == 0) {
226 u8 local_buf[8] = { 0 };
227
228 memcpy(local_buf, msg->buf, msg->len);
229 data_reg_lo = cpu_to_le32(*((u32 *)local_buf));
230 data_reg_hi = cpu_to_le32(*((u32 *)(local_buf+4)));
231
232 ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR |
233 (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT;
234
235 writel_relaxed(data_reg_lo,
236 drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO);
237 writel_relaxed(data_reg_hi,
238 drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI);
239
240 } else {
241 ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_RD |
242 (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT;
243 }
244
245 /* Execute transaction */
246 writel(ctrl_reg, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
247
248 return 0;
249}
250
251static void
252mv64xxx_i2c_update_offload_data(struct mv64xxx_i2c_data *drv_data)
253{
254 struct i2c_msg *msg = drv_data->msg;
255
256 if (msg->flags & I2C_M_RD) {
257 u32 data_reg_lo = readl(drv_data->reg_base +
258 MV64XXX_I2C_REG_RX_DATA_LO);
259 u32 data_reg_hi = readl(drv_data->reg_base +
260 MV64XXX_I2C_REG_RX_DATA_HI);
261 u8 local_buf[8] = { 0 };
262
263 *((u32 *)local_buf) = le32_to_cpu(data_reg_lo);
264 *((u32 *)(local_buf+4)) = le32_to_cpu(data_reg_hi);
265 memcpy(msg->buf, local_buf, msg->len);
266 }
267
268}
168/* 269/*
169 ***************************************************************************** 270 *****************************************************************************
170 * 271 *
@@ -177,6 +278,15 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
177static void 278static void
178mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) 279mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
179{ 280{
281 if (drv_data->offload_enabled) {
282 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
283 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING);
284 writel(0, drv_data->reg_base +
285 MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE);
286 writel(0, drv_data->reg_base +
287 MV64XXX_I2C_REG_BRIDGE_INTR_MASK);
288 }
289
180 writel(0, drv_data->reg_base + drv_data->reg_offsets.soft_reset); 290 writel(0, drv_data->reg_base + drv_data->reg_offsets.soft_reset);
181 writel(MV64XXX_I2C_BAUD_DIV_M(drv_data->freq_m) | MV64XXX_I2C_BAUD_DIV_N(drv_data->freq_n), 291 writel(MV64XXX_I2C_BAUD_DIV_M(drv_data->freq_m) | MV64XXX_I2C_BAUD_DIV_N(drv_data->freq_n),
182 drv_data->reg_base + drv_data->reg_offsets.clock); 292 drv_data->reg_base + drv_data->reg_offsets.clock);
@@ -283,6 +393,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
283 drv_data->rc = -ENXIO; 393 drv_data->rc = -ENXIO;
284 break; 394 break;
285 395
396 case MV64XXX_I2C_STATUS_OFFLOAD_OK:
397 if (drv_data->send_stop || drv_data->aborting) {
398 drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP;
399 drv_data->state = MV64XXX_I2C_STATE_IDLE;
400 } else {
401 drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_RESTART;
402 drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_RESTART;
403 }
404 break;
405
286 default: 406 default:
287 dev_err(&drv_data->adapter.dev, 407 dev_err(&drv_data->adapter.dev,
288 "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " 408 "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, "
@@ -299,20 +419,27 @@ static void
299mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) 419mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
300{ 420{
301 switch(drv_data->action) { 421 switch(drv_data->action) {
422 case MV64XXX_I2C_ACTION_OFFLOAD_RESTART:
423 mv64xxx_i2c_update_offload_data(drv_data);
424 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
425 writel(0, drv_data->reg_base +
426 MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE);
427 /* FALLTHRU */
302 case MV64XXX_I2C_ACTION_SEND_RESTART: 428 case MV64XXX_I2C_ACTION_SEND_RESTART:
303 /* We should only get here if we have further messages */ 429 /* We should only get here if we have further messages */
304 BUG_ON(drv_data->num_msgs == 0); 430 BUG_ON(drv_data->num_msgs == 0);
305 431
306 drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
307 writel(drv_data->cntl_bits,
308 drv_data->reg_base + drv_data->reg_offsets.control);
309
310 drv_data->msgs++; 432 drv_data->msgs++;
311 drv_data->num_msgs--; 433 drv_data->num_msgs--;
434 if (!(drv_data->offload_enabled &&
435 mv64xxx_i2c_offload_msg(drv_data))) {
436 drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
437 writel(drv_data->cntl_bits,
438 drv_data->reg_base + drv_data->reg_offsets.control);
312 439
313 /* Setup for the next message */ 440 /* Setup for the next message */
314 mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); 441 mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
315 442 }
316 /* 443 /*
317 * We're never at the start of the message here, and by this 444 * We're never at the start of the message here, and by this
318 * time it's already too late to do any protocol mangling. 445 * time it's already too late to do any protocol mangling.
@@ -326,6 +453,12 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
326 drv_data->reg_base + drv_data->reg_offsets.control); 453 drv_data->reg_base + drv_data->reg_offsets.control);
327 break; 454 break;
328 455
456 case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START:
457 if (!mv64xxx_i2c_offload_msg(drv_data))
458 break;
459 else
460 drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
461 /* FALLTHRU */
329 case MV64XXX_I2C_ACTION_SEND_START: 462 case MV64XXX_I2C_ACTION_SEND_START:
330 writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, 463 writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
331 drv_data->reg_base + drv_data->reg_offsets.control); 464 drv_data->reg_base + drv_data->reg_offsets.control);
@@ -375,6 +508,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
375 "mv64xxx_i2c_do_action: Invalid action: %d\n", 508 "mv64xxx_i2c_do_action: Invalid action: %d\n",
376 drv_data->action); 509 drv_data->action);
377 drv_data->rc = -EIO; 510 drv_data->rc = -EIO;
511
378 /* FALLTHRU */ 512 /* FALLTHRU */
379 case MV64XXX_I2C_ACTION_SEND_STOP: 513 case MV64XXX_I2C_ACTION_SEND_STOP:
380 drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; 514 drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
@@ -383,6 +517,15 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
383 drv_data->block = 0; 517 drv_data->block = 0;
384 wake_up(&drv_data->waitq); 518 wake_up(&drv_data->waitq);
385 break; 519 break;
520
521 case MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP:
522 mv64xxx_i2c_update_offload_data(drv_data);
523 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
524 writel(0, drv_data->reg_base +
525 MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE);
526 drv_data->block = 0;
527 wake_up(&drv_data->waitq);
528 break;
386 } 529 }
387} 530}
388 531
@@ -395,6 +538,21 @@ mv64xxx_i2c_intr(int irq, void *dev_id)
395 irqreturn_t rc = IRQ_NONE; 538 irqreturn_t rc = IRQ_NONE;
396 539
397 spin_lock_irqsave(&drv_data->lock, flags); 540 spin_lock_irqsave(&drv_data->lock, flags);
541
542 if (drv_data->offload_enabled) {
543 while (readl(drv_data->reg_base +
544 MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) {
545 int reg_status = readl(drv_data->reg_base +
546 MV64XXX_I2C_REG_BRIDGE_STATUS);
547 if (reg_status & MV64XXX_I2C_BRIDGE_STATUS_ERROR)
548 status = MV64XXX_I2C_STATUS_OFFLOAD_ERROR;
549 else
550 status = MV64XXX_I2C_STATUS_OFFLOAD_OK;
551 mv64xxx_i2c_fsm(drv_data, status);
552 mv64xxx_i2c_do_action(drv_data);
553 rc = IRQ_HANDLED;
554 }
555 }
398 while (readl(drv_data->reg_base + drv_data->reg_offsets.control) & 556 while (readl(drv_data->reg_base + drv_data->reg_offsets.control) &
399 MV64XXX_I2C_REG_CONTROL_IFLG) { 557 MV64XXX_I2C_REG_CONTROL_IFLG) {
400 status = readl(drv_data->reg_base + drv_data->reg_offsets.status); 558 status = readl(drv_data->reg_base + drv_data->reg_offsets.status);
@@ -459,11 +617,15 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
459 unsigned long flags; 617 unsigned long flags;
460 618
461 spin_lock_irqsave(&drv_data->lock, flags); 619 spin_lock_irqsave(&drv_data->lock, flags);
462 mv64xxx_i2c_prepare_for_io(drv_data, msg); 620 if (drv_data->offload_enabled) {
463 621 drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START;
464 drv_data->action = MV64XXX_I2C_ACTION_SEND_START; 622 drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
465 drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; 623 } else {
624 mv64xxx_i2c_prepare_for_io(drv_data, msg);
466 625
626 drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
627 drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
628 }
467 drv_data->send_stop = is_last; 629 drv_data->send_stop = is_last;
468 drv_data->block = 1; 630 drv_data->block = 1;
469 mv64xxx_i2c_do_action(drv_data); 631 mv64xxx_i2c_do_action(drv_data);
@@ -521,6 +683,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
521static const struct of_device_id mv64xxx_i2c_of_match_table[] = { 683static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
522 { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i}, 684 { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i},
523 { .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, 685 { .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
686 { .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
524 {} 687 {}
525}; 688};
526MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); 689MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
@@ -601,6 +764,13 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
601 764
602 memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets)); 765 memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets));
603 766
767 /*
768 * For controllers embedded in new SoCs activate the
769 * Transaction Generator support.
770 */
771 if (of_device_is_compatible(np, "marvell,mv78230-i2c"))
772 drv_data->offload_enabled = true;
773
604out: 774out:
605 return rc; 775 return rc;
606#endif 776#endif
@@ -654,6 +824,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
654 drv_data->freq_n = pdata->freq_n; 824 drv_data->freq_n = pdata->freq_n;
655 drv_data->irq = platform_get_irq(pd, 0); 825 drv_data->irq = platform_get_irq(pd, 0);
656 drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); 826 drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
827 drv_data->offload_enabled = false;
657 memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets)); 828 memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets));
658 } else if (pd->dev.of_node) { 829 } else if (pd->dev.of_node) {
659 rc = mv64xxx_of_config(drv_data, &pd->dev); 830 rc = mv64xxx_of_config(drv_data, &pd->dev);