.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Aspeed 24XX/25XX I2C Controller. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2012-2017 ASPEED Technology Inc. |
---|
5 | 6 | * Copyright 2017 IBM Corporation |
---|
6 | 7 | * Copyright 2017 Google, Inc. |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #include <linux/clk.h> |
---|
.. | .. |
---|
72 | 69 | * These share bit definitions, so use the same values for the enable & |
---|
73 | 70 | * status bits. |
---|
74 | 71 | */ |
---|
| 72 | +#define ASPEED_I2CD_INTR_RECV_MASK 0xf000ffff |
---|
75 | 73 | #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14) |
---|
76 | 74 | #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13) |
---|
77 | 75 | #define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7) |
---|
.. | .. |
---|
82 | 80 | #define ASPEED_I2CD_INTR_RX_DONE BIT(2) |
---|
83 | 81 | #define ASPEED_I2CD_INTR_TX_NAK BIT(1) |
---|
84 | 82 | #define ASPEED_I2CD_INTR_TX_ACK BIT(0) |
---|
| 83 | +#define ASPEED_I2CD_INTR_MASTER_ERRORS \ |
---|
| 84 | + (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \ |
---|
| 85 | + ASPEED_I2CD_INTR_SCL_TIMEOUT | \ |
---|
| 86 | + ASPEED_I2CD_INTR_ABNORMAL | \ |
---|
| 87 | + ASPEED_I2CD_INTR_ARBIT_LOSS) |
---|
85 | 88 | #define ASPEED_I2CD_INTR_ALL \ |
---|
86 | 89 | (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \ |
---|
87 | 90 | ASPEED_I2CD_INTR_BUS_RECOVER_DONE | \ |
---|
.. | .. |
---|
106 | 109 | #define ASPEED_I2CD_S_TX_CMD BIT(2) |
---|
107 | 110 | #define ASPEED_I2CD_M_TX_CMD BIT(1) |
---|
108 | 111 | #define ASPEED_I2CD_M_START_CMD BIT(0) |
---|
| 112 | +#define ASPEED_I2CD_MASTER_CMDS_MASK \ |
---|
| 113 | + (ASPEED_I2CD_M_STOP_CMD | \ |
---|
| 114 | + ASPEED_I2CD_M_S_RX_CMD_LAST | \ |
---|
| 115 | + ASPEED_I2CD_M_RX_CMD | \ |
---|
| 116 | + ASPEED_I2CD_M_TX_CMD | \ |
---|
| 117 | + ASPEED_I2CD_M_START_CMD) |
---|
109 | 118 | |
---|
110 | 119 | /* 0x18 : I2CD Slave Device Address Register */ |
---|
111 | 120 | #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) |
---|
112 | 121 | |
---|
113 | 122 | enum aspeed_i2c_master_state { |
---|
114 | 123 | ASPEED_I2C_MASTER_INACTIVE, |
---|
| 124 | + ASPEED_I2C_MASTER_PENDING, |
---|
115 | 125 | ASPEED_I2C_MASTER_START, |
---|
116 | 126 | ASPEED_I2C_MASTER_TX_FIRST, |
---|
117 | 127 | ASPEED_I2C_MASTER_TX, |
---|
.. | .. |
---|
121 | 131 | }; |
---|
122 | 132 | |
---|
123 | 133 | enum aspeed_i2c_slave_state { |
---|
124 | | - ASPEED_I2C_SLAVE_STOP, |
---|
| 134 | + ASPEED_I2C_SLAVE_INACTIVE, |
---|
125 | 135 | ASPEED_I2C_SLAVE_START, |
---|
126 | 136 | ASPEED_I2C_SLAVE_READ_REQUESTED, |
---|
127 | 137 | ASPEED_I2C_SLAVE_READ_PROCESSED, |
---|
128 | 138 | ASPEED_I2C_SLAVE_WRITE_REQUESTED, |
---|
129 | 139 | ASPEED_I2C_SLAVE_WRITE_RECEIVED, |
---|
| 140 | + ASPEED_I2C_SLAVE_STOP, |
---|
130 | 141 | }; |
---|
131 | 142 | |
---|
132 | 143 | struct aspeed_i2c_bus { |
---|
.. | .. |
---|
151 | 162 | int cmd_err; |
---|
152 | 163 | /* Protected only by i2c_lock_bus */ |
---|
153 | 164 | int master_xfer_result; |
---|
| 165 | + /* Multi-master */ |
---|
| 166 | + bool multi_master; |
---|
154 | 167 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
---|
155 | 168 | struct i2c_client *slave; |
---|
156 | 169 | enum aspeed_i2c_slave_state slave_state; |
---|
.. | .. |
---|
228 | 241 | } |
---|
229 | 242 | |
---|
230 | 243 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
---|
231 | | -static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus) |
---|
| 244 | +static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) |
---|
232 | 245 | { |
---|
233 | | - u32 command, irq_status, status_ack = 0; |
---|
| 246 | + u32 command, irq_handled = 0; |
---|
234 | 247 | struct i2c_client *slave = bus->slave; |
---|
235 | | - bool irq_handled = true; |
---|
236 | 248 | u8 value; |
---|
237 | 249 | |
---|
238 | | - if (!slave) { |
---|
239 | | - irq_handled = false; |
---|
240 | | - goto out; |
---|
241 | | - } |
---|
| 250 | + if (!slave) |
---|
| 251 | + return 0; |
---|
242 | 252 | |
---|
243 | 253 | command = readl(bus->base + ASPEED_I2C_CMD_REG); |
---|
244 | | - irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
245 | 254 | |
---|
246 | 255 | /* Slave was requested, restart state machine. */ |
---|
247 | 256 | if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) { |
---|
248 | | - status_ack |= ASPEED_I2CD_INTR_SLAVE_MATCH; |
---|
| 257 | + irq_handled |= ASPEED_I2CD_INTR_SLAVE_MATCH; |
---|
249 | 258 | bus->slave_state = ASPEED_I2C_SLAVE_START; |
---|
250 | 259 | } |
---|
251 | 260 | |
---|
252 | 261 | /* Slave is not currently active, irq was for someone else. */ |
---|
253 | | - if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) { |
---|
254 | | - irq_handled = false; |
---|
255 | | - goto out; |
---|
256 | | - } |
---|
| 262 | + if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE) |
---|
| 263 | + return irq_handled; |
---|
257 | 264 | |
---|
258 | 265 | dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n", |
---|
259 | 266 | irq_status, command); |
---|
.. | .. |
---|
270 | 277 | bus->slave_state = |
---|
271 | 278 | ASPEED_I2C_SLAVE_WRITE_REQUESTED; |
---|
272 | 279 | } |
---|
273 | | - status_ack |= ASPEED_I2CD_INTR_RX_DONE; |
---|
| 280 | + irq_handled |= ASPEED_I2CD_INTR_RX_DONE; |
---|
274 | 281 | } |
---|
275 | 282 | |
---|
276 | 283 | /* Slave was asked to stop. */ |
---|
277 | 284 | if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) { |
---|
278 | | - status_ack |= ASPEED_I2CD_INTR_NORMAL_STOP; |
---|
| 285 | + irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP; |
---|
279 | 286 | bus->slave_state = ASPEED_I2C_SLAVE_STOP; |
---|
280 | 287 | } |
---|
281 | | - if (irq_status & ASPEED_I2CD_INTR_TX_NAK) { |
---|
282 | | - status_ack |= ASPEED_I2CD_INTR_TX_NAK; |
---|
| 288 | + if (irq_status & ASPEED_I2CD_INTR_TX_NAK && |
---|
| 289 | + bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) { |
---|
| 290 | + irq_handled |= ASPEED_I2CD_INTR_TX_NAK; |
---|
283 | 291 | bus->slave_state = ASPEED_I2C_SLAVE_STOP; |
---|
284 | 292 | } |
---|
285 | 293 | |
---|
286 | 294 | switch (bus->slave_state) { |
---|
287 | 295 | case ASPEED_I2C_SLAVE_READ_REQUESTED: |
---|
288 | | - if (irq_status & ASPEED_I2CD_INTR_TX_ACK) |
---|
| 296 | + if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_ACK)) |
---|
289 | 297 | dev_err(bus->dev, "Unexpected ACK on read request.\n"); |
---|
290 | 298 | bus->slave_state = ASPEED_I2C_SLAVE_READ_PROCESSED; |
---|
291 | | - |
---|
292 | 299 | i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value); |
---|
293 | 300 | writel(value, bus->base + ASPEED_I2C_BYTE_BUF_REG); |
---|
294 | 301 | writel(ASPEED_I2CD_S_TX_CMD, bus->base + ASPEED_I2C_CMD_REG); |
---|
295 | 302 | break; |
---|
296 | 303 | case ASPEED_I2C_SLAVE_READ_PROCESSED: |
---|
297 | | - status_ack |= ASPEED_I2CD_INTR_TX_ACK; |
---|
298 | | - if (!(irq_status & ASPEED_I2CD_INTR_TX_ACK)) |
---|
| 304 | + if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) { |
---|
299 | 305 | dev_err(bus->dev, |
---|
300 | 306 | "Expected ACK after processed read.\n"); |
---|
| 307 | + break; |
---|
| 308 | + } |
---|
| 309 | + irq_handled |= ASPEED_I2CD_INTR_TX_ACK; |
---|
301 | 310 | i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value); |
---|
302 | 311 | writel(value, bus->base + ASPEED_I2C_BYTE_BUF_REG); |
---|
303 | 312 | writel(ASPEED_I2CD_S_TX_CMD, bus->base + ASPEED_I2C_CMD_REG); |
---|
.. | .. |
---|
311 | 320 | break; |
---|
312 | 321 | case ASPEED_I2C_SLAVE_STOP: |
---|
313 | 322 | i2c_slave_event(slave, I2C_SLAVE_STOP, &value); |
---|
| 323 | + bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; |
---|
| 324 | + break; |
---|
| 325 | + case ASPEED_I2C_SLAVE_START: |
---|
| 326 | + /* Slave was just started. Waiting for the next event. */; |
---|
314 | 327 | break; |
---|
315 | 328 | default: |
---|
316 | | - dev_err(bus->dev, "unhandled slave_state: %d\n", |
---|
| 329 | + dev_err(bus->dev, "unknown slave_state: %d\n", |
---|
317 | 330 | bus->slave_state); |
---|
| 331 | + bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; |
---|
318 | 332 | break; |
---|
319 | 333 | } |
---|
320 | 334 | |
---|
321 | | - if (status_ack != irq_status) |
---|
322 | | - dev_err(bus->dev, |
---|
323 | | - "irq handled != irq. expected %x, but was %x\n", |
---|
324 | | - irq_status, status_ack); |
---|
325 | | - writel(status_ack, bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
326 | | - |
---|
327 | | -out: |
---|
328 | 335 | return irq_handled; |
---|
329 | 336 | } |
---|
330 | 337 | #endif /* CONFIG_I2C_SLAVE */ |
---|
.. | .. |
---|
335 | 342 | u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD; |
---|
336 | 343 | struct i2c_msg *msg = &bus->msgs[bus->msgs_index]; |
---|
337 | 344 | u8 slave_addr = i2c_8bit_addr_from_msg(msg); |
---|
| 345 | + |
---|
| 346 | +#if IS_ENABLED(CONFIG_I2C_SLAVE) |
---|
| 347 | + /* |
---|
| 348 | + * If it's requested in the middle of a slave session, set the master |
---|
| 349 | + * state to 'pending' then H/W will continue handling this master |
---|
| 350 | + * command when the bus comes back to the idle state. |
---|
| 351 | + */ |
---|
| 352 | + if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) { |
---|
| 353 | + bus->master_state = ASPEED_I2C_MASTER_PENDING; |
---|
| 354 | + return; |
---|
| 355 | + } |
---|
| 356 | +#endif /* CONFIG_I2C_SLAVE */ |
---|
338 | 357 | |
---|
339 | 358 | bus->master_state = ASPEED_I2C_MASTER_START; |
---|
340 | 359 | bus->buf_index = 0; |
---|
.. | .. |
---|
381 | 400 | return 0; |
---|
382 | 401 | } |
---|
383 | 402 | |
---|
384 | | -static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus) |
---|
| 403 | +static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) |
---|
385 | 404 | { |
---|
386 | | - u32 irq_status, status_ack = 0, command = 0; |
---|
| 405 | + u32 irq_handled = 0, command = 0; |
---|
387 | 406 | struct i2c_msg *msg; |
---|
388 | 407 | u8 recv_byte; |
---|
389 | 408 | int ret; |
---|
390 | 409 | |
---|
391 | | - irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
392 | | - /* Ack all interrupt bits. */ |
---|
393 | | - writel(irq_status, bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
394 | | - |
---|
395 | 410 | if (irq_status & ASPEED_I2CD_INTR_BUS_RECOVER_DONE) { |
---|
396 | 411 | bus->master_state = ASPEED_I2C_MASTER_INACTIVE; |
---|
397 | | - status_ack |= ASPEED_I2CD_INTR_BUS_RECOVER_DONE; |
---|
| 412 | + irq_handled |= ASPEED_I2CD_INTR_BUS_RECOVER_DONE; |
---|
398 | 413 | goto out_complete; |
---|
399 | 414 | } |
---|
400 | 415 | |
---|
.. | .. |
---|
404 | 419 | * INACTIVE state. |
---|
405 | 420 | */ |
---|
406 | 421 | ret = aspeed_i2c_is_irq_error(irq_status); |
---|
407 | | - if (ret < 0) { |
---|
| 422 | + if (ret) { |
---|
408 | 423 | dev_dbg(bus->dev, "received error interrupt: 0x%08x\n", |
---|
409 | 424 | irq_status); |
---|
410 | | - bus->cmd_err = ret; |
---|
411 | | - bus->master_state = ASPEED_I2C_MASTER_INACTIVE; |
---|
412 | | - goto out_complete; |
---|
| 425 | + irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS); |
---|
| 426 | + if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) { |
---|
| 427 | + bus->cmd_err = ret; |
---|
| 428 | + bus->master_state = ASPEED_I2C_MASTER_INACTIVE; |
---|
| 429 | + goto out_complete; |
---|
| 430 | + } |
---|
413 | 431 | } |
---|
| 432 | + |
---|
| 433 | + /* Master is not currently active, irq was for someone else. */ |
---|
| 434 | + if (bus->master_state == ASPEED_I2C_MASTER_INACTIVE || |
---|
| 435 | + bus->master_state == ASPEED_I2C_MASTER_PENDING) |
---|
| 436 | + goto out_no_complete; |
---|
414 | 437 | |
---|
415 | 438 | /* We are in an invalid state; reset bus to a known state. */ |
---|
416 | 439 | if (!bus->msgs) { |
---|
417 | | - dev_err(bus->dev, "bus in unknown state\n"); |
---|
| 440 | + dev_err(bus->dev, "bus in unknown state. irq_status: 0x%x\n", |
---|
| 441 | + irq_status); |
---|
418 | 442 | bus->cmd_err = -EIO; |
---|
419 | | - if (bus->master_state != ASPEED_I2C_MASTER_STOP) |
---|
| 443 | + if (bus->master_state != ASPEED_I2C_MASTER_STOP && |
---|
| 444 | + bus->master_state != ASPEED_I2C_MASTER_INACTIVE) |
---|
420 | 445 | aspeed_i2c_do_stop(bus); |
---|
421 | 446 | goto out_no_complete; |
---|
422 | 447 | } |
---|
.. | .. |
---|
428 | 453 | * then update the state and handle the new state below. |
---|
429 | 454 | */ |
---|
430 | 455 | if (bus->master_state == ASPEED_I2C_MASTER_START) { |
---|
| 456 | +#if IS_ENABLED(CONFIG_I2C_SLAVE) |
---|
| 457 | + /* |
---|
| 458 | + * If a peer master starts a xfer immediately after it queues a |
---|
| 459 | + * master command, clear the queued master command and change |
---|
| 460 | + * its state to 'pending'. To simplify handling of pending |
---|
| 461 | + * cases, it uses S/W solution instead of H/W command queue |
---|
| 462 | + * handling. |
---|
| 463 | + */ |
---|
| 464 | + if (unlikely(irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH)) { |
---|
| 465 | + writel(readl(bus->base + ASPEED_I2C_CMD_REG) & |
---|
| 466 | + ~ASPEED_I2CD_MASTER_CMDS_MASK, |
---|
| 467 | + bus->base + ASPEED_I2C_CMD_REG); |
---|
| 468 | + bus->master_state = ASPEED_I2C_MASTER_PENDING; |
---|
| 469 | + dev_dbg(bus->dev, |
---|
| 470 | + "master goes pending due to a slave start\n"); |
---|
| 471 | + goto out_no_complete; |
---|
| 472 | + } |
---|
| 473 | +#endif /* CONFIG_I2C_SLAVE */ |
---|
431 | 474 | if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) { |
---|
| 475 | + if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_NAK))) { |
---|
| 476 | + bus->cmd_err = -ENXIO; |
---|
| 477 | + bus->master_state = ASPEED_I2C_MASTER_INACTIVE; |
---|
| 478 | + goto out_complete; |
---|
| 479 | + } |
---|
432 | 480 | pr_devel("no slave present at %02x\n", msg->addr); |
---|
433 | | - status_ack |= ASPEED_I2CD_INTR_TX_NAK; |
---|
| 481 | + irq_handled |= ASPEED_I2CD_INTR_TX_NAK; |
---|
434 | 482 | bus->cmd_err = -ENXIO; |
---|
435 | 483 | aspeed_i2c_do_stop(bus); |
---|
436 | 484 | goto out_no_complete; |
---|
437 | 485 | } |
---|
438 | | - status_ack |= ASPEED_I2CD_INTR_TX_ACK; |
---|
| 486 | + irq_handled |= ASPEED_I2CD_INTR_TX_ACK; |
---|
439 | 487 | if (msg->len == 0) { /* SMBUS_QUICK */ |
---|
440 | 488 | aspeed_i2c_do_stop(bus); |
---|
441 | 489 | goto out_no_complete; |
---|
.. | .. |
---|
450 | 498 | case ASPEED_I2C_MASTER_TX: |
---|
451 | 499 | if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_NAK)) { |
---|
452 | 500 | dev_dbg(bus->dev, "slave NACKed TX\n"); |
---|
453 | | - status_ack |= ASPEED_I2CD_INTR_TX_NAK; |
---|
| 501 | + irq_handled |= ASPEED_I2CD_INTR_TX_NAK; |
---|
454 | 502 | goto error_and_stop; |
---|
455 | 503 | } else if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) { |
---|
456 | 504 | dev_err(bus->dev, "slave failed to ACK TX\n"); |
---|
457 | 505 | goto error_and_stop; |
---|
458 | 506 | } |
---|
459 | | - status_ack |= ASPEED_I2CD_INTR_TX_ACK; |
---|
460 | | - /* fallthrough intended */ |
---|
| 507 | + irq_handled |= ASPEED_I2CD_INTR_TX_ACK; |
---|
| 508 | + fallthrough; |
---|
461 | 509 | case ASPEED_I2C_MASTER_TX_FIRST: |
---|
462 | 510 | if (bus->buf_index < msg->len) { |
---|
463 | 511 | bus->master_state = ASPEED_I2C_MASTER_TX; |
---|
.. | .. |
---|
473 | 521 | /* RX may not have completed yet (only address cycle) */ |
---|
474 | 522 | if (!(irq_status & ASPEED_I2CD_INTR_RX_DONE)) |
---|
475 | 523 | goto out_no_complete; |
---|
476 | | - /* fallthrough intended */ |
---|
| 524 | + fallthrough; |
---|
477 | 525 | case ASPEED_I2C_MASTER_RX: |
---|
478 | 526 | if (unlikely(!(irq_status & ASPEED_I2CD_INTR_RX_DONE))) { |
---|
479 | 527 | dev_err(bus->dev, "master failed to RX\n"); |
---|
480 | 528 | goto error_and_stop; |
---|
481 | 529 | } |
---|
482 | | - status_ack |= ASPEED_I2CD_INTR_RX_DONE; |
---|
| 530 | + irq_handled |= ASPEED_I2CD_INTR_RX_DONE; |
---|
483 | 531 | |
---|
484 | 532 | recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; |
---|
485 | 533 | msg->buf[bus->buf_index++] = recv_byte; |
---|
.. | .. |
---|
507 | 555 | goto out_no_complete; |
---|
508 | 556 | case ASPEED_I2C_MASTER_STOP: |
---|
509 | 557 | if (unlikely(!(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))) { |
---|
510 | | - dev_err(bus->dev, "master failed to STOP\n"); |
---|
| 558 | + dev_err(bus->dev, |
---|
| 559 | + "master failed to STOP. irq_status:0x%x\n", |
---|
| 560 | + irq_status); |
---|
511 | 561 | bus->cmd_err = -EIO; |
---|
512 | 562 | /* Do not STOP as we have already tried. */ |
---|
513 | 563 | } else { |
---|
514 | | - status_ack |= ASPEED_I2CD_INTR_NORMAL_STOP; |
---|
| 564 | + irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP; |
---|
515 | 565 | } |
---|
516 | 566 | |
---|
517 | 567 | bus->master_state = ASPEED_I2C_MASTER_INACTIVE; |
---|
.. | .. |
---|
541 | 591 | bus->master_xfer_result = bus->msgs_index + 1; |
---|
542 | 592 | complete(&bus->cmd_complete); |
---|
543 | 593 | out_no_complete: |
---|
544 | | - if (irq_status != status_ack) |
---|
545 | | - dev_err(bus->dev, |
---|
546 | | - "irq handled != irq. expected 0x%08x, but was 0x%08x\n", |
---|
547 | | - irq_status, status_ack); |
---|
548 | | - return !!irq_status; |
---|
| 594 | + return irq_handled; |
---|
549 | 595 | } |
---|
550 | 596 | |
---|
551 | 597 | static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id) |
---|
552 | 598 | { |
---|
553 | 599 | struct aspeed_i2c_bus *bus = dev_id; |
---|
554 | | - bool ret; |
---|
| 600 | + u32 irq_received, irq_remaining, irq_handled; |
---|
555 | 601 | |
---|
556 | 602 | spin_lock(&bus->lock); |
---|
| 603 | + irq_received = readl(bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
| 604 | + /* Ack all interrupts except for Rx done */ |
---|
| 605 | + writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE, |
---|
| 606 | + bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
| 607 | + readl(bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
| 608 | + irq_received &= ASPEED_I2CD_INTR_RECV_MASK; |
---|
| 609 | + irq_remaining = irq_received; |
---|
557 | 610 | |
---|
558 | 611 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
---|
559 | | - if (IS_ENABLED(CONFIG_I2C_SLAVE) && aspeed_i2c_slave_irq(bus)) { |
---|
560 | | - dev_dbg(bus->dev, "irq handled by slave.\n"); |
---|
561 | | - ret = true; |
---|
562 | | - goto out; |
---|
| 612 | + /* |
---|
| 613 | + * In most cases, interrupt bits will be set one by one, although |
---|
| 614 | + * multiple interrupt bits could be set at the same time. It's also |
---|
| 615 | + * possible that master interrupt bits could be set along with slave |
---|
| 616 | + * interrupt bits. Each case needs to be handled using corresponding |
---|
| 617 | + * handlers depending on the current state. |
---|
| 618 | + */ |
---|
| 619 | + if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE && |
---|
| 620 | + bus->master_state != ASPEED_I2C_MASTER_PENDING) { |
---|
| 621 | + irq_handled = aspeed_i2c_master_irq(bus, irq_remaining); |
---|
| 622 | + irq_remaining &= ~irq_handled; |
---|
| 623 | + if (irq_remaining) |
---|
| 624 | + irq_handled |= aspeed_i2c_slave_irq(bus, irq_remaining); |
---|
| 625 | + } else { |
---|
| 626 | + irq_handled = aspeed_i2c_slave_irq(bus, irq_remaining); |
---|
| 627 | + irq_remaining &= ~irq_handled; |
---|
| 628 | + if (irq_remaining) |
---|
| 629 | + irq_handled |= aspeed_i2c_master_irq(bus, |
---|
| 630 | + irq_remaining); |
---|
563 | 631 | } |
---|
| 632 | + |
---|
| 633 | + /* |
---|
| 634 | + * Start a pending master command at here if a slave operation is |
---|
| 635 | + * completed. |
---|
| 636 | + */ |
---|
| 637 | + if (bus->master_state == ASPEED_I2C_MASTER_PENDING && |
---|
| 638 | + bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE) |
---|
| 639 | + aspeed_i2c_do_start(bus); |
---|
| 640 | +#else |
---|
| 641 | + irq_handled = aspeed_i2c_master_irq(bus, irq_remaining); |
---|
564 | 642 | #endif /* CONFIG_I2C_SLAVE */ |
---|
565 | 643 | |
---|
566 | | - ret = aspeed_i2c_master_irq(bus); |
---|
| 644 | + irq_remaining &= ~irq_handled; |
---|
| 645 | + if (irq_remaining) |
---|
| 646 | + dev_err(bus->dev, |
---|
| 647 | + "irq handled != irq. expected 0x%08x, but was 0x%08x\n", |
---|
| 648 | + irq_received, irq_handled); |
---|
567 | 649 | |
---|
568 | | -#if IS_ENABLED(CONFIG_I2C_SLAVE) |
---|
569 | | -out: |
---|
570 | | -#endif |
---|
| 650 | + /* Ack Rx done */ |
---|
| 651 | + if (irq_received & ASPEED_I2CD_INTR_RX_DONE) { |
---|
| 652 | + writel(ASPEED_I2CD_INTR_RX_DONE, |
---|
| 653 | + bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
| 654 | + readl(bus->base + ASPEED_I2C_INTR_STS_REG); |
---|
| 655 | + } |
---|
571 | 656 | spin_unlock(&bus->lock); |
---|
572 | | - return ret ? IRQ_HANDLED : IRQ_NONE; |
---|
| 657 | + return irq_remaining ? IRQ_NONE : IRQ_HANDLED; |
---|
573 | 658 | } |
---|
574 | 659 | |
---|
575 | 660 | static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, |
---|
.. | .. |
---|
577 | 662 | { |
---|
578 | 663 | struct aspeed_i2c_bus *bus = i2c_get_adapdata(adap); |
---|
579 | 664 | unsigned long time_left, flags; |
---|
580 | | - int ret = 0; |
---|
581 | 665 | |
---|
582 | 666 | spin_lock_irqsave(&bus->lock, flags); |
---|
583 | 667 | bus->cmd_err = 0; |
---|
584 | 668 | |
---|
585 | | - /* If bus is busy, attempt recovery. We assume a single master |
---|
586 | | - * environment. |
---|
587 | | - */ |
---|
588 | | - if (readl(bus->base + ASPEED_I2C_CMD_REG) & ASPEED_I2CD_BUS_BUSY_STS) { |
---|
| 669 | + /* If bus is busy in a single master environment, attempt recovery. */ |
---|
| 670 | + if (!bus->multi_master && |
---|
| 671 | + (readl(bus->base + ASPEED_I2C_CMD_REG) & |
---|
| 672 | + ASPEED_I2CD_BUS_BUSY_STS)) { |
---|
| 673 | + int ret; |
---|
| 674 | + |
---|
589 | 675 | spin_unlock_irqrestore(&bus->lock, flags); |
---|
590 | 676 | ret = aspeed_i2c_recover_bus(bus); |
---|
591 | 677 | if (ret) |
---|
.. | .. |
---|
605 | 691 | time_left = wait_for_completion_timeout(&bus->cmd_complete, |
---|
606 | 692 | bus->adap.timeout); |
---|
607 | 693 | |
---|
608 | | - if (time_left == 0) |
---|
| 694 | + if (time_left == 0) { |
---|
| 695 | + /* |
---|
| 696 | + * In a multi-master setup, if a timeout occurs, attempt |
---|
| 697 | + * recovery. But if the bus is idle, we still need to reset the |
---|
| 698 | + * i2c controller to clear the remaining interrupts. |
---|
| 699 | + */ |
---|
| 700 | + if (bus->multi_master && |
---|
| 701 | + (readl(bus->base + ASPEED_I2C_CMD_REG) & |
---|
| 702 | + ASPEED_I2CD_BUS_BUSY_STS)) |
---|
| 703 | + aspeed_i2c_recover_bus(bus); |
---|
| 704 | + else |
---|
| 705 | + aspeed_i2c_reset(bus); |
---|
| 706 | + |
---|
| 707 | + /* |
---|
| 708 | + * If timed out and the state is still pending, drop the pending |
---|
| 709 | + * master command. |
---|
| 710 | + */ |
---|
| 711 | + spin_lock_irqsave(&bus->lock, flags); |
---|
| 712 | + if (bus->master_state == ASPEED_I2C_MASTER_PENDING) |
---|
| 713 | + bus->master_state = ASPEED_I2C_MASTER_INACTIVE; |
---|
| 714 | + spin_unlock_irqrestore(&bus->lock, flags); |
---|
| 715 | + |
---|
609 | 716 | return -ETIMEDOUT; |
---|
610 | | - else |
---|
611 | | - return bus->master_xfer_result; |
---|
| 717 | + } |
---|
| 718 | + |
---|
| 719 | + return bus->master_xfer_result; |
---|
612 | 720 | } |
---|
613 | 721 | |
---|
614 | 722 | static u32 aspeed_i2c_functionality(struct i2c_adapter *adap) |
---|
.. | .. |
---|
648 | 756 | __aspeed_i2c_reg_slave(bus, client->addr); |
---|
649 | 757 | |
---|
650 | 758 | bus->slave = client; |
---|
651 | | - bus->slave_state = ASPEED_I2C_SLAVE_STOP; |
---|
| 759 | + bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; |
---|
652 | 760 | spin_unlock_irqrestore(&bus->lock, flags); |
---|
653 | 761 | |
---|
654 | 762 | return 0; |
---|
.. | .. |
---|
803 | 911 | if (ret < 0) |
---|
804 | 912 | return ret; |
---|
805 | 913 | |
---|
806 | | - if (!of_property_read_bool(pdev->dev.of_node, "multi-master")) |
---|
| 914 | + if (of_property_read_bool(pdev->dev.of_node, "multi-master")) |
---|
| 915 | + bus->multi_master = true; |
---|
| 916 | + else |
---|
807 | 917 | fun_ctrl_reg |= ASPEED_I2CD_MULTI_MASTER_DIS; |
---|
808 | 918 | |
---|
809 | 919 | /* Enable Master Mode */ |
---|
.. | .. |
---|
850 | 960 | .compatible = "aspeed,ast2500-i2c-bus", |
---|
851 | 961 | .data = aspeed_i2c_25xx_get_clk_reg_val, |
---|
852 | 962 | }, |
---|
| 963 | + { |
---|
| 964 | + .compatible = "aspeed,ast2600-i2c-bus", |
---|
| 965 | + .data = aspeed_i2c_25xx_get_clk_reg_val, |
---|
| 966 | + }, |
---|
853 | 967 | { }, |
---|
854 | 968 | }; |
---|
855 | 969 | MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table); |
---|
.. | .. |
---|
891 | 1005 | if (ret < 0) { |
---|
892 | 1006 | dev_err(&pdev->dev, |
---|
893 | 1007 | "Could not read bus-frequency property\n"); |
---|
894 | | - bus->bus_frequency = 100000; |
---|
| 1008 | + bus->bus_frequency = I2C_MAX_STANDARD_MODE_FREQ; |
---|
895 | 1009 | } |
---|
896 | 1010 | |
---|
897 | 1011 | match = of_match_node(aspeed_i2c_bus_of_table, pdev->dev.of_node); |
---|
.. | .. |
---|
906 | 1020 | init_completion(&bus->cmd_complete); |
---|
907 | 1021 | bus->adap.owner = THIS_MODULE; |
---|
908 | 1022 | bus->adap.retries = 0; |
---|
909 | | - bus->adap.timeout = 5 * HZ; |
---|
910 | 1023 | bus->adap.algo = &aspeed_i2c_algo; |
---|
911 | 1024 | bus->adap.dev.parent = &pdev->dev; |
---|
912 | 1025 | bus->adap.dev.of_node = pdev->dev.of_node; |
---|