Skip to content

Commit 470a662

Browse files
sknseanwsakernel
authored andcommitted
i2c: stm32f7: Add atomic_xfer method to driver
Add an atomic_xfer method to the driver so that it behaves correctly when controlling a PMIC that is responsible for device shutdown. The atomic_xfer method added is similar to the one from the i2c-mv64xxx driver. When running an atomic_xfer a bool flag in the driver data is set, the interrupt is not unmasked on transfer start, and the IRQ handler is manually invoked while waiting for pending transfers to complete. Signed-off-by: Sean Nyekjaer <[email protected]> Acked-by: Andi Shyti <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 3a133a4 commit 470a662

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

drivers/i2c/busses/i2c-stm32f7.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ struct stm32f7_i2c_dev {
357357
u32 dnf_dt;
358358
u32 dnf;
359359
struct stm32f7_i2c_alert *alert;
360+
bool atomic;
360361
};
361362

362363
/*
@@ -915,7 +916,8 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
915916

916917
/* Configure DMA or enable RX/TX interrupt */
917918
i2c_dev->use_dma = false;
918-
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
919+
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN
920+
&& !i2c_dev->atomic) {
919921
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
920922
msg->flags & I2C_M_RD,
921923
f7_msg->count, f7_msg->buf,
@@ -939,6 +941,9 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
939941
cr1 |= STM32F7_I2C_CR1_TXDMAEN;
940942
}
941943

944+
if (i2c_dev->atomic)
945+
cr1 &= ~STM32F7_I2C_ALL_IRQ_MASK; /* Disable all interrupts */
946+
942947
/* Configure Start/Repeated Start */
943948
cr2 |= STM32F7_I2C_CR2_START;
944949

@@ -1670,7 +1675,22 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
16701675
return IRQ_HANDLED;
16711676
}
16721677

1673-
static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
1678+
static int stm32f7_i2c_wait_polling(struct stm32f7_i2c_dev *i2c_dev)
1679+
{
1680+
ktime_t timeout = ktime_add_ms(ktime_get(), i2c_dev->adap.timeout);
1681+
1682+
while (ktime_compare(ktime_get(), timeout) < 0) {
1683+
udelay(5);
1684+
stm32f7_i2c_isr_event(0, i2c_dev);
1685+
1686+
if (completion_done(&i2c_dev->complete))
1687+
return 1;
1688+
}
1689+
1690+
return 0;
1691+
}
1692+
1693+
static int stm32f7_i2c_xfer_core(struct i2c_adapter *i2c_adap,
16741694
struct i2c_msg msgs[], int num)
16751695
{
16761696
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
@@ -1694,8 +1714,12 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
16941714

16951715
stm32f7_i2c_xfer_msg(i2c_dev, msgs);
16961716

1697-
time_left = wait_for_completion_timeout(&i2c_dev->complete,
1698-
i2c_dev->adap.timeout);
1717+
if (!i2c_dev->atomic)
1718+
time_left = wait_for_completion_timeout(&i2c_dev->complete,
1719+
i2c_dev->adap.timeout);
1720+
else
1721+
time_left = stm32f7_i2c_wait_polling(i2c_dev);
1722+
16991723
ret = f7_msg->result;
17001724
if (ret) {
17011725
if (i2c_dev->use_dma)
@@ -1727,6 +1751,24 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
17271751
return (ret < 0) ? ret : num;
17281752
}
17291753

1754+
static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
1755+
struct i2c_msg msgs[], int num)
1756+
{
1757+
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
1758+
1759+
i2c_dev->atomic = false;
1760+
return stm32f7_i2c_xfer_core(i2c_adap, msgs, num);
1761+
}
1762+
1763+
static int stm32f7_i2c_xfer_atomic(struct i2c_adapter *i2c_adap,
1764+
struct i2c_msg msgs[], int num)
1765+
{
1766+
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
1767+
1768+
i2c_dev->atomic = true;
1769+
return stm32f7_i2c_xfer_core(i2c_adap, msgs, num);
1770+
}
1771+
17301772
static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
17311773
unsigned short flags, char read_write,
17321774
u8 command, int size,
@@ -2095,6 +2137,7 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
20952137

20962138
static const struct i2c_algorithm stm32f7_i2c_algo = {
20972139
.master_xfer = stm32f7_i2c_xfer,
2140+
.master_xfer_atomic = stm32f7_i2c_xfer_atomic,
20982141
.smbus_xfer = stm32f7_i2c_smbus_xfer,
20992142
.functionality = stm32f7_i2c_func,
21002143
.reg_slave = stm32f7_i2c_reg_slave,

0 commit comments

Comments
 (0)