Commit 7ecc8cfd authored by Pierre-Yves MORDRET's avatar Pierre-Yves MORDRET Committed by Wolfram Sang

i2c: i2c-stm32f7: Add DMA support

This patch adds DMA support for i2c-stm32f7 driver
Signed-off-by: default avatarM'boumba Cedric Madianga <cedric.madianga@gmail.com>
Signed-off-by: default avatarPierre-Yves MORDRET <pierre-yves.mordret@st.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent bb8822cb
...@@ -94,7 +94,8 @@ obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o ...@@ -94,7 +94,8 @@ obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o
obj-$(CONFIG_I2C_ST) += i2c-st.o obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o i2c-stm32f7-drv-objs := i2c-stm32f7.o i2c-stm32.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7-drv.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
/* STM32F7 I2C control 1 */ /* STM32F7 I2C control 1 */
#define STM32F7_I2C_CR1_PECEN BIT(23) #define STM32F7_I2C_CR1_PECEN BIT(23)
#define STM32F7_I2C_CR1_SBC BIT(16) #define STM32F7_I2C_CR1_SBC BIT(16)
#define STM32F7_I2C_CR1_RXDMAEN BIT(15)
#define STM32F7_I2C_CR1_TXDMAEN BIT(14)
#define STM32F7_I2C_CR1_ANFOFF BIT(12) #define STM32F7_I2C_CR1_ANFOFF BIT(12)
#define STM32F7_I2C_CR1_ERRIE BIT(7) #define STM32F7_I2C_CR1_ERRIE BIT(7)
#define STM32F7_I2C_CR1_TCIE BIT(6) #define STM32F7_I2C_CR1_TCIE BIT(6)
...@@ -142,6 +144,7 @@ ...@@ -142,6 +144,7 @@
#define STM32F7_I2C_TIMINGR_SCLL(n) ((n) & 0xff) #define STM32F7_I2C_TIMINGR_SCLL(n) ((n) & 0xff)
#define STM32F7_I2C_MAX_LEN 0xff #define STM32F7_I2C_MAX_LEN 0xff
#define STM32F7_I2C_DMA_LEN_MIN 0x16
#define STM32F7_I2C_MAX_SLAVE 0x2 #define STM32F7_I2C_MAX_SLAVE 0x2
#define STM32F7_I2C_DNF_DEFAULT 0 #define STM32F7_I2C_DNF_DEFAULT 0
...@@ -270,6 +273,8 @@ struct stm32f7_i2c_msg { ...@@ -270,6 +273,8 @@ struct stm32f7_i2c_msg {
* @slave_dir: transfer direction for the current slave device * @slave_dir: transfer direction for the current slave device
* @master_mode: boolean to know in which mode the I2C is running (master or * @master_mode: boolean to know in which mode the I2C is running (master or
* slave) * slave)
* @dma: dma data
* @use_dma: boolean to know if dma is used in the current transfer
*/ */
struct stm32f7_i2c_dev { struct stm32f7_i2c_dev {
struct i2c_adapter adap; struct i2c_adapter adap;
...@@ -288,6 +293,8 @@ struct stm32f7_i2c_dev { ...@@ -288,6 +293,8 @@ struct stm32f7_i2c_dev {
struct i2c_client *slave_running; struct i2c_client *slave_running;
u32 slave_dir; u32 slave_dir;
bool master_mode; bool master_mode;
struct stm32_i2c_dma *dma;
bool use_dma;
}; };
/** /**
...@@ -599,6 +606,25 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, ...@@ -599,6 +606,25 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
return 0; return 0;
} }
static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)
{
void __iomem *base = i2c_dev->base;
u32 mask = STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN;
stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
}
static void stm32f7_i2c_dma_callback(void *arg)
{
struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg;
struct stm32_i2c_dma *dma = i2c_dev->dma;
struct device *dev = dma->chan_using->device->dev;
stm32f7_i2c_disable_dma_req(i2c_dev);
dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir);
complete(&dma->dma_complete);
}
static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev) static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
{ {
struct stm32f7_i2c_timings *t = &i2c_dev->timing; struct stm32f7_i2c_timings *t = &i2c_dev->timing;
...@@ -653,6 +679,9 @@ static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev) ...@@ -653,6 +679,9 @@ static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
u32 cr2; u32 cr2;
if (i2c_dev->use_dma)
f7_msg->count -= STM32F7_I2C_MAX_LEN;
cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2); cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
cr2 &= ~STM32F7_I2C_CR2_NBYTES_MASK; cr2 &= ~STM32F7_I2C_CR2_NBYTES_MASK;
...@@ -712,6 +741,7 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, ...@@ -712,6 +741,7 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base; void __iomem *base = i2c_dev->base;
u32 cr1, cr2; u32 cr1, cr2;
int ret;
f7_msg->addr = msg->addr; f7_msg->addr = msg->addr;
f7_msg->buf = msg->buf; f7_msg->buf = msg->buf;
...@@ -753,14 +783,35 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, ...@@ -753,14 +783,35 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE | cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE; STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
/* Clear TX/RX interrupt */ /* Clear DMA req and TX/RX interrupt */
cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE); cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
/* Configure DMA or enable RX/TX interrupt */
i2c_dev->use_dma = false;
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
msg->flags & I2C_M_RD,
f7_msg->count, f7_msg->buf,
stm32f7_i2c_dma_callback,
i2c_dev);
if (!ret)
i2c_dev->use_dma = true;
else
dev_warn(i2c_dev->dev, "can't use DMA\n");
}
/* Enable RX/TX interrupt according to msg direction */ if (!i2c_dev->use_dma) {
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
cr1 |= STM32F7_I2C_CR1_RXIE; cr1 |= STM32F7_I2C_CR1_RXIE;
else else
cr1 |= STM32F7_I2C_CR1_TXIE; cr1 |= STM32F7_I2C_CR1_TXIE;
} else {
if (msg->flags & I2C_M_RD)
cr1 |= STM32F7_I2C_CR1_RXDMAEN;
else
cr1 |= STM32F7_I2C_CR1_TXDMAEN;
}
/* Configure Start/Repeated Start */ /* Configure Start/Repeated Start */
cr2 |= STM32F7_I2C_CR2_START; cr2 |= STM32F7_I2C_CR2_START;
...@@ -780,7 +831,7 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, ...@@ -780,7 +831,7 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
struct device *dev = i2c_dev->dev; struct device *dev = i2c_dev->dev;
void __iomem *base = i2c_dev->base; void __iomem *base = i2c_dev->base;
u32 cr1, cr2; u32 cr1, cr2;
int i; int i, ret;
f7_msg->result = 0; f7_msg->result = 0;
reinit_completion(&i2c_dev->complete); reinit_completion(&i2c_dev->complete);
...@@ -895,14 +946,35 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, ...@@ -895,14 +946,35 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE | cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE; STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
/* Clear TX/RX interrupt */ /* Clear DMA req and TX/RX interrupt */
cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE); cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
/* Configure DMA or enable RX/TX interrupt */
i2c_dev->use_dma = false;
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
cr2 & STM32F7_I2C_CR2_RD_WRN,
f7_msg->count, f7_msg->buf,
stm32f7_i2c_dma_callback,
i2c_dev);
if (!ret)
i2c_dev->use_dma = true;
else
dev_warn(i2c_dev->dev, "can't use DMA\n");
}
/* Enable RX/TX interrupt according to msg direction */ if (!i2c_dev->use_dma) {
if (cr2 & STM32F7_I2C_CR2_RD_WRN) if (cr2 & STM32F7_I2C_CR2_RD_WRN)
cr1 |= STM32F7_I2C_CR1_RXIE; cr1 |= STM32F7_I2C_CR1_RXIE;
else else
cr1 |= STM32F7_I2C_CR1_TXIE; cr1 |= STM32F7_I2C_CR1_TXIE;
} else {
if (cr2 & STM32F7_I2C_CR2_RD_WRN)
cr1 |= STM32F7_I2C_CR1_RXDMAEN;
else
cr1 |= STM32F7_I2C_CR1_TXDMAEN;
}
/* Set Start bit */ /* Set Start bit */
cr2 |= STM32F7_I2C_CR2_START; cr2 |= STM32F7_I2C_CR2_START;
...@@ -921,6 +993,7 @@ static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev) ...@@ -921,6 +993,7 @@ static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base; void __iomem *base = i2c_dev->base;
u32 cr1, cr2; u32 cr1, cr2;
int ret;
cr2 = readl_relaxed(base + STM32F7_I2C_CR2); cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
cr1 = readl_relaxed(base + STM32F7_I2C_CR1); cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
...@@ -960,6 +1033,35 @@ static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev) ...@@ -960,6 +1033,35 @@ static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev)
cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE); cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE);
cr1 |= STM32F7_I2C_CR1_RXIE; cr1 |= STM32F7_I2C_CR1_RXIE;
/*
* Configure DMA or enable RX/TX interrupt:
* For I2C_SMBUS_BLOCK_DATA and I2C_SMBUS_BLOCK_PROC_CALL we don't use
* dma as we don't know in advance how many data will be received
*/
cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
i2c_dev->use_dma = false;
if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN &&
f7_msg->size != I2C_SMBUS_BLOCK_DATA &&
f7_msg->size != I2C_SMBUS_BLOCK_PROC_CALL) {
ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
cr2 & STM32F7_I2C_CR2_RD_WRN,
f7_msg->count, f7_msg->buf,
stm32f7_i2c_dma_callback,
i2c_dev);
if (!ret)
i2c_dev->use_dma = true;
else
dev_warn(i2c_dev->dev, "can't use DMA\n");
}
if (!i2c_dev->use_dma)
cr1 |= STM32F7_I2C_CR1_RXIE;
else
cr1 |= STM32F7_I2C_CR1_RXDMAEN;
/* Configure Repeated Start */ /* Configure Repeated Start */
cr2 |= STM32F7_I2C_CR2_START; cr2 |= STM32F7_I2C_CR2_START;
...@@ -1248,7 +1350,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) ...@@ -1248,7 +1350,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base; void __iomem *base = i2c_dev->base;
u32 status, mask; u32 status, mask;
int ret; int ret = IRQ_HANDLED;
/* Check if the interrupt if for a slave device */ /* Check if the interrupt if for a slave device */
if (!i2c_dev->master_mode) { if (!i2c_dev->master_mode) {
...@@ -1285,15 +1387,21 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) ...@@ -1285,15 +1387,21 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
/* Clear STOP flag */ /* Clear STOP flag */
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
if (i2c_dev->use_dma) {
ret = IRQ_WAKE_THREAD;
} else {
i2c_dev->master_mode = false; i2c_dev->master_mode = false;
complete(&i2c_dev->complete); complete(&i2c_dev->complete);
} }
}
/* Transfer complete */ /* Transfer complete */
if (status & STM32F7_I2C_ISR_TC) { if (status & STM32F7_I2C_ISR_TC) {
if (f7_msg->stop) { if (f7_msg->stop) {
mask = STM32F7_I2C_CR2_STOP; mask = STM32F7_I2C_CR2_STOP;
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask); stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
} else if (i2c_dev->use_dma) {
ret = IRQ_WAKE_THREAD;
} else if (f7_msg->smbus) { } else if (f7_msg->smbus) {
stm32f7_i2c_smbus_rep_start(i2c_dev); stm32f7_i2c_smbus_rep_start(i2c_dev);
} else { } else {
...@@ -1310,6 +1418,44 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) ...@@ -1310,6 +1418,44 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
stm32f7_i2c_reload(i2c_dev); stm32f7_i2c_reload(i2c_dev);
} }
return ret;
}
static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
{
struct stm32f7_i2c_dev *i2c_dev = data;
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
struct stm32_i2c_dma *dma = i2c_dev->dma;
u32 status;
int ret;
/*
* Wait for dma transfer completion before sending next message or
* notity the end of xfer to the client
*/
ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
if (!ret) {
dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
stm32f7_i2c_disable_dma_req(i2c_dev);
dmaengine_terminate_all(dma->chan_using);
f7_msg->result = -ETIMEDOUT;
}
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
if (status & STM32F7_I2C_ISR_TC) {
if (f7_msg->smbus) {
stm32f7_i2c_smbus_rep_start(i2c_dev);
} else {
i2c_dev->msg_id++;
i2c_dev->msg++;
stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
}
} else {
i2c_dev->master_mode = false;
complete(&i2c_dev->complete);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1319,6 +1465,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) ...@@ -1319,6 +1465,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base; void __iomem *base = i2c_dev->base;
struct device *dev = i2c_dev->dev; struct device *dev = i2c_dev->dev;
struct stm32_i2c_dma *dma = i2c_dev->dma;
u32 mask, status; u32 mask, status;
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR); status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
...@@ -1350,6 +1497,12 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) ...@@ -1350,6 +1497,12 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
mask = STM32F7_I2C_ALL_IRQ_MASK; mask = STM32F7_I2C_ALL_IRQ_MASK;
stm32f7_i2c_disable_irq(i2c_dev, mask); stm32f7_i2c_disable_irq(i2c_dev, mask);
/* Disable dma */
if (i2c_dev->use_dma) {
stm32f7_i2c_disable_dma_req(i2c_dev);
dmaengine_terminate_all(dma->chan_using);
}
i2c_dev->master_mode = false; i2c_dev->master_mode = false;
complete(&i2c_dev->complete); complete(&i2c_dev->complete);
...@@ -1361,6 +1514,7 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -1361,6 +1514,7 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
{ {
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
struct stm32_i2c_dma *dma = i2c_dev->dma;
unsigned long time_left; unsigned long time_left;
int ret; int ret;
...@@ -1388,6 +1542,8 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -1388,6 +1542,8 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!time_left) { if (!time_left) {
dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n", dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
i2c_dev->msg->addr); i2c_dev->msg->addr);
if (i2c_dev->use_dma)
dmaengine_terminate_all(dma->chan_using);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} }
...@@ -1404,6 +1560,7 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, ...@@ -1404,6 +1560,7 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
{ {
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adapter); struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adapter);
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
struct stm32_i2c_dma *dma = i2c_dev->dma;
struct device *dev = i2c_dev->dev; struct device *dev = i2c_dev->dev;
unsigned long timeout; unsigned long timeout;
int i, ret; int i, ret;
...@@ -1435,6 +1592,8 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, ...@@ -1435,6 +1592,8 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
if (!timeout) { if (!timeout) {
dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr); dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
if (i2c_dev->use_dma)
dmaengine_terminate_all(dma->chan_using);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto clk_free; goto clk_free;
} }
...@@ -1608,6 +1767,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1608,6 +1767,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
u32 irq_error, irq_event, clk_rate, rise_time, fall_time; u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct reset_control *rst; struct reset_control *rst;
dma_addr_t phy_addr;
int ret; int ret;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
...@@ -1618,6 +1778,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1618,6 +1778,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(i2c_dev->base)) if (IS_ERR(i2c_dev->base))
return PTR_ERR(i2c_dev->base); return PTR_ERR(i2c_dev->base);
phy_addr = (dma_addr_t)res->start;
irq_event = irq_of_parse_and_map(np, 0); irq_event = irq_of_parse_and_map(np, 0);
if (!irq_event) { if (!irq_event) {
...@@ -1664,7 +1825,10 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1664,7 +1825,10 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
i2c_dev->dev = &pdev->dev; i2c_dev->dev = &pdev->dev;
ret = devm_request_irq(&pdev->dev, irq_event, stm32f7_i2c_isr_event, 0, ret = devm_request_threaded_irq(&pdev->dev, irq_event,
stm32f7_i2c_isr_event,
stm32f7_i2c_isr_event_thread,
IRQF_ONESHOT,
pdev->name, i2c_dev); pdev->name, i2c_dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request irq event %i\n", dev_err(&pdev->dev, "Failed to request irq event %i\n",
...@@ -1717,6 +1881,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1717,6 +1881,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
init_completion(&i2c_dev->complete); init_completion(&i2c_dev->complete);
/* Init DMA config if supported */
i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
STM32F7_I2C_TXDR,
STM32F7_I2C_RXDR);
ret = i2c_add_adapter(adap); ret = i2c_add_adapter(adap);
if (ret) if (ret)
goto clk_free; goto clk_free;
...@@ -1739,6 +1908,11 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) ...@@ -1739,6 +1908,11 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
{ {
struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
if (i2c_dev->dma) {
stm32_i2c_dma_free(i2c_dev->dma);
i2c_dev->dma = NULL;
}
i2c_del_adapter(&i2c_dev->adap); i2c_del_adapter(&i2c_dev->adap);
clk_unprepare(i2c_dev->clk); clk_unprepare(i2c_dev->clk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment