|
@@ -441,6 +441,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
|
|
|
u16 control_reg;
|
|
|
u16 restart_flag = 0;
|
|
|
u32 reg_4g_mode;
|
|
|
+ u8 *dma_rd_buf = NULL;
|
|
|
+ u8 *dma_wr_buf = NULL;
|
|
|
dma_addr_t rpaddr = 0;
|
|
|
dma_addr_t wpaddr = 0;
|
|
|
int ret;
|
|
@@ -500,10 +502,18 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
|
|
|
if (i2c->op == I2C_MASTER_RD) {
|
|
|
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
|
|
|
writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
|
|
|
- rpaddr = dma_map_single(i2c->dev, msgs->buf,
|
|
|
+
|
|
|
+ dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
|
|
|
+ if (!dma_rd_buf)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ rpaddr = dma_map_single(i2c->dev, dma_rd_buf,
|
|
|
msgs->len, DMA_FROM_DEVICE);
|
|
|
- if (dma_mapping_error(i2c->dev, rpaddr))
|
|
|
+ if (dma_mapping_error(i2c->dev, rpaddr)) {
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, false);
|
|
|
+
|
|
|
return -ENOMEM;
|
|
|
+ }
|
|
|
|
|
|
if (i2c->dev_comp->support_33bits) {
|
|
|
reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);
|
|
@@ -515,10 +525,18 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
|
|
|
} else if (i2c->op == I2C_MASTER_WR) {
|
|
|
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
|
|
|
writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
|
|
|
- wpaddr = dma_map_single(i2c->dev, msgs->buf,
|
|
|
+
|
|
|
+ dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
|
|
|
+ if (!dma_wr_buf)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
|
|
|
msgs->len, DMA_TO_DEVICE);
|
|
|
- if (dma_mapping_error(i2c->dev, wpaddr))
|
|
|
+ if (dma_mapping_error(i2c->dev, wpaddr)) {
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
|
|
|
+
|
|
|
return -ENOMEM;
|
|
|
+ }
|
|
|
|
|
|
if (i2c->dev_comp->support_33bits) {
|
|
|
reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
|
|
@@ -530,16 +548,39 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
|
|
|
} else {
|
|
|
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
|
|
|
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);
|
|
|
- wpaddr = dma_map_single(i2c->dev, msgs->buf,
|
|
|
+
|
|
|
+ dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
|
|
|
+ if (!dma_wr_buf)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
|
|
|
msgs->len, DMA_TO_DEVICE);
|
|
|
- if (dma_mapping_error(i2c->dev, wpaddr))
|
|
|
+ if (dma_mapping_error(i2c->dev, wpaddr)) {
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
|
|
|
+
|
|
|
return -ENOMEM;
|
|
|
- rpaddr = dma_map_single(i2c->dev, (msgs + 1)->buf,
|
|
|
+ }
|
|
|
+
|
|
|
+ dma_rd_buf = i2c_get_dma_safe_msg_buf((msgs + 1), 0);
|
|
|
+ if (!dma_rd_buf) {
|
|
|
+ dma_unmap_single(i2c->dev, wpaddr,
|
|
|
+ msgs->len, DMA_TO_DEVICE);
|
|
|
+
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
|
|
|
+
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ rpaddr = dma_map_single(i2c->dev, dma_rd_buf,
|
|
|
(msgs + 1)->len,
|
|
|
DMA_FROM_DEVICE);
|
|
|
if (dma_mapping_error(i2c->dev, rpaddr)) {
|
|
|
dma_unmap_single(i2c->dev, wpaddr,
|
|
|
msgs->len, DMA_TO_DEVICE);
|
|
|
+
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_rd_buf, (msgs + 1), false);
|
|
|
+
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
@@ -578,14 +619,21 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
|
|
|
if (i2c->op == I2C_MASTER_WR) {
|
|
|
dma_unmap_single(i2c->dev, wpaddr,
|
|
|
msgs->len, DMA_TO_DEVICE);
|
|
|
+
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, true);
|
|
|
} else if (i2c->op == I2C_MASTER_RD) {
|
|
|
dma_unmap_single(i2c->dev, rpaddr,
|
|
|
msgs->len, DMA_FROM_DEVICE);
|
|
|
+
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, true);
|
|
|
} else {
|
|
|
dma_unmap_single(i2c->dev, wpaddr, msgs->len,
|
|
|
DMA_TO_DEVICE);
|
|
|
dma_unmap_single(i2c->dev, rpaddr, (msgs + 1)->len,
|
|
|
DMA_FROM_DEVICE);
|
|
|
+
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, true);
|
|
|
+ i2c_put_dma_safe_msg_buf(dma_rd_buf, (msgs + 1), true);
|
|
|
}
|
|
|
|
|
|
if (ret == 0) {
|