diff options
Diffstat (limited to 'src/soc/mediatek/common/i2c.c')
-rw-r--r-- | src/soc/mediatek/common/i2c.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/src/soc/mediatek/common/i2c.c b/src/soc/mediatek/common/i2c.c index 87925ba169..3c54b17738 100644 --- a/src/soc/mediatek/common/i2c.c +++ b/src/soc/mediatek/common/i2c.c @@ -10,14 +10,34 @@ #include <soc/i2c.h> #include <device/i2c_simple.h> -static inline void i2c_dma_reset(struct mt_i2c_dma_regs *dma_regs) +static inline void i2c_hw_reset(uint8_t bus) { - write32(&dma_regs->dma_rst, 0x1); - udelay(50); - write32(&dma_regs->dma_rst, 0x2); - udelay(50); - write32(&dma_regs->dma_rst, 0x0); - udelay(50); + struct mt_i2c_regs *regs; + struct mt_i2c_dma_regs *dma_regs; + + regs = mtk_i2c_bus_controller[bus].i2c_regs; + dma_regs = mtk_i2c_bus_controller[bus].i2c_dma_regs; + + if (mtk_i2c_bus_controller[bus].mt_i2c_flag == I2C_APDMA_ASYNC) { + write32(&dma_regs->dma_rst, I2C_DMA_WARM_RST); + udelay(10); + write32(&dma_regs->dma_rst, I2C_DMA_CLR_FLAG); + udelay(10); + write32(&dma_regs->dma_rst, + I2C_DMA_HARD_RST | I2C_DMA_HANDSHAKE_RST); + write32(®s->softreset, I2C_SOFT_RST | I2C_HANDSHAKE_RST); + udelay(10); + write32(&dma_regs->dma_rst, I2C_DMA_CLR_FLAG); + write32(®s->softreset, I2C_CLR_FLAG); + } else { + write32(®s->softreset, I2C_SOFT_RST); + write32(&dma_regs->dma_rst, I2C_DMA_WARM_RST); + udelay(50); + write32(&dma_regs->dma_rst, I2C_DMA_HARD_RST); + udelay(50); + write32(&dma_regs->dma_rst, I2C_DMA_CLR_FLAG); + udelay(50); + } } static inline void mtk_i2c_dump_info(struct mt_i2c_regs *regs) @@ -47,6 +67,7 @@ static uint32_t mtk_i2c_transfer(uint8_t bus, struct i2c_msg *seg, { uint32_t ret_code = I2C_OK; uint16_t status; + uint16_t dma_sync = 0; uint32_t time_out_val = 0; uint8_t addr; uint32_t write_len = 0; @@ -62,6 +83,12 @@ static uint32_t mtk_i2c_transfer(uint8_t bus, struct i2c_msg *seg, addr = seg[0].slave; + if (mtk_i2c_bus_controller[bus].mt_i2c_flag == I2C_APDMA_ASYNC) { + dma_sync = I2C_DMA_SKIP_CONFIG | I2C_DMA_ASYNC_MODE; + if (mode == I2C_WRITE_READ_MODE) + dma_sync |= I2C_DMA_DIR_CHANGE; + } + switch (mode) { case I2C_WRITE_MODE: assert(seg[0].len > 0 && seg[0].len <= 255); @@ -113,7 +140,7 @@ static uint32_t mtk_i2c_transfer(uint8_t bus, struct i2c_msg *seg, write32(®s->slave_addr, addr << 1); /* Prepare buffer data to start transfer */ - write32(&dma_regs->dma_con, I2C_DMA_CON_TX); + write32(&dma_regs->dma_con, I2C_DMA_CON_TX | dma_sync); write32(&dma_regs->dma_tx_mem_addr, (uintptr_t)_dma_coherent); write32(&dma_regs->dma_tx_len, write_len); break; @@ -132,7 +159,7 @@ static uint32_t mtk_i2c_transfer(uint8_t bus, struct i2c_msg *seg, write32(®s->slave_addr, (addr << 1 | 0x1)); /* Prepare buffer data to start transfer */ - write32(&dma_regs->dma_con, I2C_DMA_CON_RX); + write32(&dma_regs->dma_con, I2C_DMA_CON_RX | dma_sync); write32(&dma_regs->dma_rx_mem_addr, (uintptr_t)_dma_coherent); write32(&dma_regs->dma_rx_len, read_len); break; @@ -154,7 +181,7 @@ static uint32_t mtk_i2c_transfer(uint8_t bus, struct i2c_msg *seg, write32(®s->slave_addr, addr << 1); /* Prepare buffer data to start transfer */ - write32(&dma_regs->dma_con, I2C_DMA_CLR_FLAG); + write32(&dma_regs->dma_con, I2C_DMA_CLR_FLAG | dma_sync); write32(&dma_regs->dma_tx_mem_addr, (uintptr_t)_dma_coherent); write32(&dma_regs->dma_tx_len, write_len); write32(&dma_regs->dma_rx_mem_addr, (uintptr_t)_dma_coherent); @@ -206,9 +233,7 @@ static uint32_t mtk_i2c_transfer(uint8_t bus, struct i2c_msg *seg, I2C_TRANSAC_COMP); /* reset the i2c controller for next i2c transfer. */ - write32(®s->softreset, 0x1); - - i2c_dma_reset(dma_regs); + i2c_hw_reset(bus); return ret_code; } |