Skip to content

Commit fc66b39

Browse files
Jun GaoWolfram Sang
authored andcommitted
i2c: mediatek: Use DMA safe buffers for i2c transactions
DMA mode will always be used in i2c transactions, try to allocate a DMA safe buffer if the buf of struct i2c_msg used is not DMA safe. Signed-off-by: Jun Gao <jun.gao@mediatek.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
1 parent 9cbeeca commit fc66b39

File tree

1 file changed

+55
-7
lines changed

1 file changed

+55
-7
lines changed

drivers/i2c/busses/i2c-mt65xx.c

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
441441
u16 control_reg;
442442
u16 restart_flag = 0;
443443
u32 reg_4g_mode;
444+
u8 *dma_rd_buf = NULL;
445+
u8 *dma_wr_buf = NULL;
444446
dma_addr_t rpaddr = 0;
445447
dma_addr_t wpaddr = 0;
446448
int ret;
@@ -500,10 +502,18 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
500502
if (i2c->op == I2C_MASTER_RD) {
501503
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
502504
writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
503-
rpaddr = dma_map_single(i2c->dev, msgs->buf,
505+
506+
dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
507+
if (!dma_rd_buf)
508+
return -ENOMEM;
509+
510+
rpaddr = dma_map_single(i2c->dev, dma_rd_buf,
504511
msgs->len, DMA_FROM_DEVICE);
505-
if (dma_mapping_error(i2c->dev, rpaddr))
512+
if (dma_mapping_error(i2c->dev, rpaddr)) {
513+
i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, false);
514+
506515
return -ENOMEM;
516+
}
507517

508518
if (i2c->dev_comp->support_33bits) {
509519
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,
515525
} else if (i2c->op == I2C_MASTER_WR) {
516526
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
517527
writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
518-
wpaddr = dma_map_single(i2c->dev, msgs->buf,
528+
529+
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
530+
if (!dma_wr_buf)
531+
return -ENOMEM;
532+
533+
wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
519534
msgs->len, DMA_TO_DEVICE);
520-
if (dma_mapping_error(i2c->dev, wpaddr))
535+
if (dma_mapping_error(i2c->dev, wpaddr)) {
536+
i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
537+
521538
return -ENOMEM;
539+
}
522540

523541
if (i2c->dev_comp->support_33bits) {
524542
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,
530548
} else {
531549
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
532550
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);
533-
wpaddr = dma_map_single(i2c->dev, msgs->buf,
551+
552+
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
553+
if (!dma_wr_buf)
554+
return -ENOMEM;
555+
556+
wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
534557
msgs->len, DMA_TO_DEVICE);
535-
if (dma_mapping_error(i2c->dev, wpaddr))
558+
if (dma_mapping_error(i2c->dev, wpaddr)) {
559+
i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
560+
536561
return -ENOMEM;
537-
rpaddr = dma_map_single(i2c->dev, (msgs + 1)->buf,
562+
}
563+
564+
dma_rd_buf = i2c_get_dma_safe_msg_buf((msgs + 1), 0);
565+
if (!dma_rd_buf) {
566+
dma_unmap_single(i2c->dev, wpaddr,
567+
msgs->len, DMA_TO_DEVICE);
568+
569+
i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
570+
571+
return -ENOMEM;
572+
}
573+
574+
rpaddr = dma_map_single(i2c->dev, dma_rd_buf,
538575
(msgs + 1)->len,
539576
DMA_FROM_DEVICE);
540577
if (dma_mapping_error(i2c->dev, rpaddr)) {
541578
dma_unmap_single(i2c->dev, wpaddr,
542579
msgs->len, DMA_TO_DEVICE);
580+
581+
i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
582+
i2c_put_dma_safe_msg_buf(dma_rd_buf, (msgs + 1), false);
583+
543584
return -ENOMEM;
544585
}
545586

@@ -578,14 +619,21 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
578619
if (i2c->op == I2C_MASTER_WR) {
579620
dma_unmap_single(i2c->dev, wpaddr,
580621
msgs->len, DMA_TO_DEVICE);
622+
623+
i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, true);
581624
} else if (i2c->op == I2C_MASTER_RD) {
582625
dma_unmap_single(i2c->dev, rpaddr,
583626
msgs->len, DMA_FROM_DEVICE);
627+
628+
i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, true);
584629
} else {
585630
dma_unmap_single(i2c->dev, wpaddr, msgs->len,
586631
DMA_TO_DEVICE);
587632
dma_unmap_single(i2c->dev, rpaddr, (msgs + 1)->len,
588633
DMA_FROM_DEVICE);
634+
635+
i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, true);
636+
i2c_put_dma_safe_msg_buf(dma_rd_buf, (msgs + 1), true);
589637
}
590638

591639
if (ret == 0) {

0 commit comments

Comments
 (0)