mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									9cbeeca050
								
							
						
					
					
						commit
						fc66b39fe3
					
				
					 1 changed files with 58 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -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,11 +502,19 @@ 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,
 | 
			
		||||
					msgs->len, DMA_FROM_DEVICE);
 | 
			
		||||
		if (dma_mapping_error(i2c->dev, rpaddr))
 | 
			
		||||
 | 
			
		||||
		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)) {
 | 
			
		||||
			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);
 | 
			
		||||
			writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
 | 
			
		||||
| 
						 | 
				
			
			@ -515,11 +525,19 @@ 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,
 | 
			
		||||
					msgs->len, DMA_TO_DEVICE);
 | 
			
		||||
		if (dma_mapping_error(i2c->dev, wpaddr))
 | 
			
		||||
 | 
			
		||||
		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)) {
 | 
			
		||||
			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);
 | 
			
		||||
			writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
 | 
			
		||||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
					msgs->len, DMA_TO_DEVICE);
 | 
			
		||||
		if (dma_mapping_error(i2c->dev, wpaddr))
 | 
			
		||||
 | 
			
		||||
		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
 | 
			
		||||
		if (!dma_wr_buf)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		rpaddr = dma_map_single(i2c->dev, (msgs + 1)->buf,
 | 
			
		||||
 | 
			
		||||
		wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
 | 
			
		||||
					msgs->len, DMA_TO_DEVICE);
 | 
			
		||||
		if (dma_mapping_error(i2c->dev, wpaddr)) {
 | 
			
		||||
			i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
 | 
			
		||||
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue