Pull i2c fixes from Wolfram Sang: "A few driver fixes for the I2C subsystem" * 'i2c/for-current-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: stm32f7: remove warning when compiling with W=1 i2c: stm32f7: fix a race in slave mode with arbitration loss irq i2c: stm32f7: fix first byte to send in slave mode i2c: mt65xx: fix NULL ptr dereference i2c: aspeed: fix master pending state handling
Showing the changes to drivers (3 of 3 files). Show all
Unified · Split
| @@ -108,6 +108,12 @@ · 107 unmodified lines | ||
| 108 | 108 | #define ASPEED_I2CD_S_TX_CMD BIT(2) |
| 109 | 109 | #define ASPEED_I2CD_M_TX_CMD BIT(1) |
| 110 | 110 | #define ASPEED_I2CD_M_START_CMD BIT(0) |
| 111 | +#define ASPEED_I2CD_MASTER_CMDS_MASK \ | |
| 112 | + (ASPEED_I2CD_M_STOP_CMD | \ | |
| 113 | + ASPEED_I2CD_M_S_RX_CMD_LAST | \ | |
| 114 | + ASPEED_I2CD_M_RX_CMD | \ | |
| 115 | + ASPEED_I2CD_M_TX_CMD | \ | |
| 116 | + ASPEED_I2CD_M_START_CMD) | |
| 111 | 117 | |
| 112 | 118 | /* 0x18 : I2CD Slave Device Address Register */ |
| 113 | 119 | #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) |
| @@ -336,18 +342,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) · 222 unmodified lines | ||
| 336 | 342 | struct i2c_msg *msg = &bus->msgs[bus->msgs_index]; |
| 337 | 343 | u8 slave_addr = i2c_8bit_addr_from_msg(msg); |
| 338 | 344 | |
| 339 | − bus->master_state = ASPEED_I2C_MASTER_START; | |
| 340 | − | |
| 341 | 345 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
| 342 | 346 | /* |
| 343 | 347 | * If it's requested in the middle of a slave session, set the master |
| 344 | 348 | * state to 'pending' then H/W will continue handling this master |
| 345 | 349 | * command when the bus comes back to the idle state. |
| 346 | 350 | */ |
| 347 | − if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) | |
| 351 | + if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) { | |
| 348 | 352 | bus->master_state = ASPEED_I2C_MASTER_PENDING; |
| 353 | + return; | |
| 354 | + } | |
| 349 | 355 | #endif /* CONFIG_I2C_SLAVE */ |
| 350 | 356 | |
| 357 | + bus->master_state = ASPEED_I2C_MASTER_START; | |
| 351 | 358 | bus->buf_index = 0; |
| 352 | 359 | |
| 353 | 360 | if (msg->flags & I2C_M_RD) { |
| @@ -422,20 +429,6 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) · 68 unmodified lines | ||
| 422 | 429 | } |
| 423 | 430 | } |
| 424 | 431 | |
| 425 | −#if IS_ENABLED(CONFIG_I2C_SLAVE) | |
| 426 | − /* | |
| 427 | − * A pending master command will be started by H/W when the bus comes | |
| 428 | − * back to idle state after completing a slave operation so change the | |
| 429 | − * master state from 'pending' to 'start' at here if slave is inactive. | |
| 430 | − */ | |
| 431 | − if (bus->master_state == ASPEED_I2C_MASTER_PENDING) { | |
| 432 | − if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) | |
| 433 | − goto out_no_complete; | |
| 434 | − | |
| 435 | − bus->master_state = ASPEED_I2C_MASTER_START; | |
| 436 | − } | |
| 437 | −#endif /* CONFIG_I2C_SLAVE */ | |
| 438 | − | |
| 439 | 432 | /* Master is not currently active, irq was for someone else. */ |
| 440 | 433 | if (bus->master_state == ASPEED_I2C_MASTER_INACTIVE || |
| 441 | 434 | bus->master_state == ASPEED_I2C_MASTER_PENDING) |
| @@ -462,11 +455,15 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) · 20 unmodified lines | ||
| 462 | 455 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
| 463 | 456 | /* |
| 464 | 457 | * If a peer master starts a xfer immediately after it queues a |
| 465 | − * master command, change its state to 'pending' then H/W will | |
| 466 | − * continue the queued master xfer just after completing the | |
| 467 | − * slave mode session. | |
| 458 | + * master command, clear the queued master command and change | |
| 459 | + * its state to 'pending'. To simplify handling of pending | |
| 460 | + * cases, it uses S/W solution instead of H/W command queue | |
| 461 | + * handling. | |
| 468 | 462 | */ |
| 469 | 463 | if (unlikely(irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH)) { |
| 464 | + writel(readl(bus->base + ASPEED_I2C_CMD_REG) & | |
| 465 | + ~ASPEED_I2CD_MASTER_CMDS_MASK, | |
| 466 | + bus->base + ASPEED_I2C_CMD_REG); | |
| 470 | 467 | bus->master_state = ASPEED_I2C_MASTER_PENDING; |
| 471 | 468 | dev_dbg(bus->dev, |
| 472 | 469 | "master goes pending due to a slave start\n"); |
| @@ -629,6 +626,14 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id) · 156 unmodified lines | ||
| 629 | 626 | irq_handled |= aspeed_i2c_master_irq(bus, |
| 630 | 627 | irq_remaining); |
| 631 | 628 | } |
| 629 | + | |
| 630 | + /* | |
| 631 | + * Start a pending master command at here if a slave operation is | |
| 632 | + * completed. | |
| 633 | + */ | |
| 634 | + if (bus->master_state == ASPEED_I2C_MASTER_PENDING && | |
| 635 | + bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE) | |
| 636 | + aspeed_i2c_do_start(bus); | |
| 632 | 637 | #else |
| 633 | 638 | irq_handled = aspeed_i2c_master_irq(bus, irq_remaining); |
| 634 | 639 | #endif /* CONFIG_I2C_SLAVE */ |
| @@ -691,6 +696,15 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, · 56 unmodified lines | ||
| 691 | 696 | ASPEED_I2CD_BUS_BUSY_STS)) |
| 692 | 697 | aspeed_i2c_recover_bus(bus); |
| 693 | 698 | |
| 699 | + /* | |
| 700 | + * If timed out and the state is still pending, drop the pending | |
| 701 | + * master command. | |
| 702 | + */ | |
| 703 | + spin_lock_irqsave(&bus->lock, flags); | |
| 704 | + if (bus->master_state == ASPEED_I2C_MASTER_PENDING) | |
| 705 | + bus->master_state = ASPEED_I2C_MASTER_INACTIVE; | |
| 706 | + spin_unlock_irqrestore(&bus->lock, flags); | |
| 707 | + | |
| 694 | 708 | return -ETIMEDOUT; |
| 695 | 709 | } |
| 696 | 710 | |
| @@ -875,7 +875,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id) · 874 unmodified lines | ||
| 875 | 875 | |
| 876 | 876 | static u32 mtk_i2c_functionality(struct i2c_adapter *adap) |
| 877 | 877 | { |
| 878 | − if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN) | |
| 878 | + if (i2c_check_quirks(adap, I2C_AQ_NO_ZERO_LEN)) | |
| 879 | 879 | return I2C_FUNC_I2C | |
| 880 | 880 | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); |
| 881 | 881 | else |
| @@ -305,7 +305,7 @@ struct stm32f7_i2c_dev { · 304 unmodified lines | ||
| 305 | 305 | struct regmap *regmap; |
| 306 | 306 | }; |
| 307 | 307 | |
| 308 | −/** | |
| 308 | +/* | |
| 309 | 309 | * All these values are coming from I2C Specification, Version 6.0, 4th of |
| 310 | 310 | * April 2014. |
| 311 | 311 | * |
| @@ -1192,6 +1192,8 @@ static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev) · 880 unmodified lines | ||
| 1192 | 1192 | STM32F7_I2C_CR1_TXIE; |
| 1193 | 1193 | stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask); |
| 1194 | 1194 | |
| 1195 | + /* Write 1st data byte */ | |
| 1196 | + writel_relaxed(value, base + STM32F7_I2C_TXDR); | |
| 1195 | 1197 | } else { |
| 1196 | 1198 | /* Notify i2c slave that new write transfer is starting */ |
| 1197 | 1199 | i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); |
| @@ -1501,7 +1503,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) · 303 unmodified lines | ||
| 1501 | 1503 | void __iomem *base = i2c_dev->base; |
| 1502 | 1504 | struct device *dev = i2c_dev->dev; |
| 1503 | 1505 | struct stm32_i2c_dma *dma = i2c_dev->dma; |
| 1504 | − u32 mask, status; | |
| 1506 | + u32 status; | |
| 1505 | 1507 | |
| 1506 | 1508 | status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR); |
| 1507 | 1509 | |
| @@ -1526,12 +1528,15 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) · 18 unmodified lines | ||
| 1526 | 1528 | f7_msg->result = -EINVAL; |
| 1527 | 1529 | } |
| 1528 | 1530 | |
| 1529 | − /* Disable interrupts */ | |
| 1530 | − if (stm32f7_i2c_is_slave_registered(i2c_dev)) | |
| 1531 | − mask = STM32F7_I2C_XFER_IRQ_MASK; | |
| 1532 | − else | |
| 1533 | − mask = STM32F7_I2C_ALL_IRQ_MASK; | |
| 1534 | − stm32f7_i2c_disable_irq(i2c_dev, mask); | |
| 1531 | + if (!i2c_dev->slave_running) { | |
| 1532 | + u32 mask; | |
| 1533 | + /* Disable interrupts */ | |
| 1534 | + if (stm32f7_i2c_is_slave_registered(i2c_dev)) | |
| 1535 | + mask = STM32F7_I2C_XFER_IRQ_MASK; | |
| 1536 | + else | |
| 1537 | + mask = STM32F7_I2C_ALL_IRQ_MASK; | |
| 1538 | + stm32f7_i2c_disable_irq(i2c_dev, mask); | |
| 1539 | + } | |
| 1535 | 1540 | |
| 1536 | 1541 | /* Disable dma */ |
| 1537 | 1542 | if (i2c_dev->use_dma) { |