mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-28 12:53:14 +01:00
Merge tag 'i2c-fixes-7.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux
Pull i2c fixes from Andi Shyti: "Three patches in xiic for fixing the block reads and a single cleanup in the at91 error path: - at91: also release DMA channels when deferring probe - xiic: fix SMBus block reads with PEC" * tag 'i2c-fixes-7.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux: i2c: at91: release DMA channels when probe defers i2c: xiic: don't clobber msg->len to signal block-read completion i2c: xiic: defer RX_FULL until all trailing bytes are in FIFO i2c: xiic: preserve PEC byte length in SMBus block read setup
This commit is contained in:
commit
7704c4c5bb
2 files changed
+53
-16
No files matched your search
@@ -921,8 +921,14 @@ int at91_twi_probe_master(struct platform_device *pdev,
|
||||
at91_calc_twi_clock(dev);
|
||||
|
||||
rc = at91_init_twi_recovery_info(pdev, dev);
|
||||
if (rc == -EPROBE_DEFER)
|
||||
if (rc == -EPROBE_DEFER) {
|
||||
/*
|
||||
* The DMA channels were already set up above, release them
|
||||
* before deferring the probe so they are not leaked.
|
||||
*/
|
||||
at91_twi_dma_release(dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dev->adapter.algo = &at91_twi_algorithm;
|
||||
dev->adapter.quirks = &at91_twi_quirks;
|
||||
|
||||
@@ -73,6 +73,9 @@ enum i2c_scl_freq {
|
||||
* @prev_msg_tx: Previous message is Tx
|
||||
* @quirks: To hold platform specific bug info
|
||||
* @smbus_block_read: Flag to handle block read
|
||||
* @smbus_actual_len: Valid byte count (length + payload + optional PEC) of a
|
||||
* padded SMBus block read. msg->len is trimmed to this on completion.
|
||||
* Zero when no trimming is needed.
|
||||
* @input_clk: Input clock to I2C controller
|
||||
* @i2c_clk: I2C SCL frequency
|
||||
* @atomic: Mode of transfer
|
||||
@@ -98,6 +101,7 @@ struct xiic_i2c {
|
||||
bool prev_msg_tx;
|
||||
u32 quirks;
|
||||
bool smbus_block_read;
|
||||
unsigned int smbus_actual_len;
|
||||
unsigned long input_clk;
|
||||
unsigned int i2c_clk;
|
||||
bool atomic;
|
||||
@@ -539,30 +543,38 @@ static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
|
||||
|
||||
/* Check if received length is valid */
|
||||
if (rxmsg_len <= I2C_SMBUS_BLOCK_MAX) {
|
||||
unsigned int pec_len = i2c->rx_msg->len - 1;
|
||||
|
||||
/* Set Receive fifo depth */
|
||||
if (rxmsg_len > IIC_RX_FIFO_DEPTH) {
|
||||
if (rxmsg_len + pec_len > IIC_RX_FIFO_DEPTH) {
|
||||
/*
|
||||
* When Rx msg len greater than or equal to Rx fifo capacity
|
||||
* Receive fifo depth should set to Rx fifo capacity minus 1
|
||||
* Trailing bytes (payload plus any PEC) exceed Rx FIFO
|
||||
* capacity, so drain in chunks. This also keeps the
|
||||
* else branch below from pushing rfd_set past the
|
||||
* 4-bit XIIC_RFD_REG_OFFSET field.
|
||||
*/
|
||||
rfd_set = IIC_RX_FIFO_DEPTH - 1;
|
||||
i2c->rx_msg->len = rxmsg_len + 1;
|
||||
} else if ((rxmsg_len == 1) ||
|
||||
(rxmsg_len == 0)) {
|
||||
i2c->rx_msg->len = rxmsg_len + 1 + pec_len;
|
||||
} else if (1 + rxmsg_len + pec_len < SMBUS_BLOCK_READ_MIN_LEN) {
|
||||
/*
|
||||
* Minimum of 3 bytes required to exit cleanly. 1 byte
|
||||
* already received, Second byte is being received. Have
|
||||
* to set NACK in read_rx before receiving the last byte
|
||||
* The HW needs SMBUS_BLOCK_READ_MIN_LEN bytes on the
|
||||
* bus to exit cleanly: by the time the ISR reads the
|
||||
* length byte the second byte is already being clocked
|
||||
* in, too late to NACK. Pad the drain target and record
|
||||
* the real length, trimmed back on completion so the
|
||||
* PEC check sees the right byte.
|
||||
*/
|
||||
rfd_set = 0;
|
||||
i2c->rx_msg->len = SMBUS_BLOCK_READ_MIN_LEN;
|
||||
i2c->smbus_actual_len = 1 + rxmsg_len + pec_len;
|
||||
} else {
|
||||
/*
|
||||
* When Rx msg len less than Rx fifo capacity
|
||||
* Receive fifo depth should set to Rx msg len minus 2
|
||||
* All trailing bytes fit in the Rx FIFO. Defer RX_FULL
|
||||
* until every one of them is buffered, so the drain
|
||||
* takes xiic_read_rx()'s bytes_rem == 0 path.
|
||||
*/
|
||||
rfd_set = rxmsg_len - 2;
|
||||
i2c->rx_msg->len = rxmsg_len + 1;
|
||||
rfd_set = rxmsg_len + pec_len - 1;
|
||||
i2c->rx_msg->len = rxmsg_len + 1 + pec_len;
|
||||
}
|
||||
xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
|
||||
|
||||
@@ -575,6 +587,16 @@ static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
|
||||
dev_err(i2c->adap.dev.parent, "smbus_block_read Invalid msg length\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the setup-time padding of a short SMBus block read before rx_msg is
|
||||
* cleared, so the PEC check sees the right byte.
|
||||
*/
|
||||
static void xiic_smbus_trim_len(struct xiic_i2c *i2c)
|
||||
{
|
||||
if (i2c->rx_msg && i2c->smbus_actual_len)
|
||||
i2c->rx_msg->len = i2c->smbus_actual_len;
|
||||
}
|
||||
|
||||
static void xiic_read_rx(struct xiic_i2c *i2c)
|
||||
{
|
||||
u8 bytes_in_fifo, cr = 0, bytes_to_read = 0;
|
||||
@@ -797,6 +819,8 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
|
||||
|
||||
xiic_read_rx(i2c);
|
||||
if (xiic_rx_space(i2c) == 0) {
|
||||
xiic_smbus_trim_len(i2c);
|
||||
|
||||
/* this is the last part of the message */
|
||||
i2c->rx_msg = NULL;
|
||||
|
||||
@@ -865,8 +889,11 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
|
||||
|
||||
if (i2c->tx_msg && i2c->smbus_block_read) {
|
||||
i2c->smbus_block_read = false;
|
||||
/* Set requested message len=1 to indicate STATE_DONE */
|
||||
i2c->tx_msg->len = 1;
|
||||
/*
|
||||
* Drive xiic_tx_space() to 0 to signal STATE_DONE
|
||||
* without truncating the rx_msg length.
|
||||
*/
|
||||
i2c->tx_pos = i2c->tx_msg->len;
|
||||
}
|
||||
|
||||
if (!i2c->tx_msg)
|
||||
@@ -938,6 +965,7 @@ static void xiic_recv_atomic(struct xiic_i2c *i2c)
|
||||
return;
|
||||
}
|
||||
|
||||
xiic_smbus_trim_len(i2c);
|
||||
i2c->rx_msg = NULL;
|
||||
xiic_irq_clr_en(i2c, XIIC_INTR_TX_ERROR_MASK);
|
||||
|
||||
@@ -955,6 +983,9 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
|
||||
u8 cr = 0, rfd_set = 0;
|
||||
struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg;
|
||||
|
||||
/* A stale value from an aborted block read would truncate this msg. */
|
||||
i2c->smbus_actual_len = 0;
|
||||
|
||||
if (!i2c->atomic)
|
||||
dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n",
|
||||
__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
|
||||
|
||||
Reference in new issue
Block a user