The Aspeed I2C controller has two register layouts. The AST2500 uses the old mode with a single DMA address register (I2CD_DMA_ADDR) where the address is 4-byte aligned and masked to 0x3ffffffc.
>From AST2600 onwards, the new mode provides separate master TX/RX and slave RX >DMA address registers (I2CM_DMA_TX_ADDR, I2CM_DMA_RX_ADDR, I2CS_DMA_RX_ADDR) with different address widths per SoC: AST2600 (new mode): 0x7fffffff - bits[30:0] AST1030 (new mode): 0x7fffffff - bits[30:0] AST1060 (new mode): 0x7fffffff - bits[30:0] AST2700 (new mode): 0xffffffff - bits[31:0] Introduce dma_addr_lo_mask as a per-class attribute and apply it uniformly when storing DMA address register writes and when loading the address into dma_dram_offset for both master and slave paths. This replaces the previous FIELD_EX32 extractions (which incorrectly stripped bit 31 on AST2700) and the hardcoded 0x3ffffffc literal in the old-mode path. Signed-off-by: Jamin Lin <[email protected]> --- include/hw/i2c/aspeed_i2c.h | 5 +---- hw/i2c/aspeed_i2c.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index d42cb4865a..1fc229f699 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -209,13 +209,9 @@ REG32(I2CS_DMA_LEN, 0x2c) FIELD(I2CS_DMA_LEN, TX_BUF_LEN_W1T, 15, 1) FIELD(I2CS_DMA_LEN, TX_BUF_LEN, 0, 11) REG32(I2CM_DMA_TX_ADDR, 0x30) - FIELD(I2CM_DMA_TX_ADDR, ADDR, 0, 31) REG32(I2CM_DMA_RX_ADDR, 0x34) - FIELD(I2CM_DMA_RX_ADDR, ADDR, 0, 31) REG32(I2CS_DMA_TX_ADDR, 0x38) - FIELD(I2CS_DMA_TX_ADDR, ADDR, 0, 31) REG32(I2CS_DMA_RX_ADDR, 0x3c) - FIELD(I2CS_DMA_RX_ADDR, ADDR, 0, 31) REG32(I2CS_DEV_ADDR, 0x40) REG32(I2CM_DMA_LEN_STS, 0x48) FIELD(I2CM_DMA_LEN_STS, RX_LEN, 16, 13) @@ -303,6 +299,7 @@ struct AspeedI2CClass { bool has_share_pool; uint64_t mem_size; bool has_dma64; + uint32_t dma_addr_lo_mask; }; static inline bool aspeed_i2c_is_new_mode(AspeedI2CState *s) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index 80c4457500..9c0387a394 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -236,7 +236,7 @@ static void aspeed_i2c_set_tx_dma_dram_offset(AspeedI2CBus *bus) value = bus->regs[R_I2CM_DMA_TX_ADDR]; bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR)); + value & aic->dma_addr_lo_mask); if (aic->has_dma64) { value = bus->regs[R_I2CM_DMA_TX_ADDR_HI]; bus->dma_dram_offset = @@ -246,7 +246,7 @@ static void aspeed_i2c_set_tx_dma_dram_offset(AspeedI2CBus *bus) } else { value = bus->regs[R_I2CD_DMA_ADDR]; bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - value & 0x3ffffffc); + value & aic->dma_addr_lo_mask); } } @@ -261,7 +261,7 @@ static void aspeed_i2c_set_rx_dma_dram_offset(AspeedI2CBus *bus) value = bus->regs[R_I2CM_DMA_RX_ADDR]; bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR)); + value & aic->dma_addr_lo_mask); if (aic->has_dma64) { value = bus->regs[R_I2CM_DMA_RX_ADDR_HI]; bus->dma_dram_offset = @@ -271,7 +271,7 @@ static void aspeed_i2c_set_rx_dma_dram_offset(AspeedI2CBus *bus) } else { value = bus->regs[R_I2CD_DMA_ADDR]; bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - value & 0x3ffffffc); + value & aic->dma_addr_lo_mask); } } @@ -735,12 +735,10 @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, aspeed_i2c_bus_raise_interrupt(bus); break; case A_I2CM_DMA_TX_ADDR: - bus->regs[R_I2CM_DMA_TX_ADDR] = FIELD_EX32(value, I2CM_DMA_TX_ADDR, - ADDR); + bus->regs[R_I2CM_DMA_TX_ADDR] = value & aic->dma_addr_lo_mask; break; case A_I2CM_DMA_RX_ADDR: - bus->regs[R_I2CM_DMA_RX_ADDR] = FIELD_EX32(value, I2CM_DMA_RX_ADDR, - ADDR); + bus->regs[R_I2CM_DMA_RX_ADDR] = value & aic->dma_addr_lo_mask; break; case A_I2CM_DMA_LEN: w1t = FIELD_EX32(value, I2CM_DMA_LEN, RX_BUF_LEN_W1T) || @@ -1385,6 +1383,8 @@ static const TypeInfo aspeed_i2c_info = { static int aspeed_i2c_bus_new_slave_event(AspeedI2CBus *bus, enum i2c_event event) { + AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller); + switch (event) { case I2C_START_SEND_ASYNC: if (!SHARED_ARRAY_FIELD_EX32(bus->regs, R_I2CS_CMD, RX_DMA_EN)) { @@ -1395,7 +1395,7 @@ static int aspeed_i2c_bus_new_slave_event(AspeedI2CBus *bus, ARRAY_FIELD_DP32(bus->regs, I2CS_DMA_LEN_STS, RX_LEN, 0); bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - ARRAY_FIELD_EX32(bus->regs, I2CS_DMA_RX_ADDR, ADDR)); + bus->regs[R_I2CS_DMA_RX_ADDR] & aic->dma_addr_lo_mask); bus->regs[R_I2CC_DMA_LEN] = ARRAY_FIELD_EX32(bus->regs, I2CS_DMA_LEN, RX_BUF_LEN) + 1; i2c_ack(bus->bus); @@ -1638,6 +1638,7 @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, const void *data) aic->check_sram = true; aic->has_dma = true; aic->mem_size = 0x1000; + aic->dma_addr_lo_mask = 0x3ffffffc; } static const TypeInfo aspeed_2500_i2c_info = { @@ -1667,6 +1668,7 @@ static void aspeed_2600_i2c_class_init(ObjectClass *klass, const void *data) aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; aic->has_dma = true; aic->mem_size = 0x1000; + aic->dma_addr_lo_mask = 0x7fffffff; } static const TypeInfo aspeed_2600_i2c_info = { @@ -1691,6 +1693,7 @@ static void aspeed_1030_i2c_class_init(ObjectClass *klass, const void *data) aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; aic->has_dma = true; aic->mem_size = 0x10000; + aic->dma_addr_lo_mask = 0x7fffffff; } static const TypeInfo aspeed_1030_i2c_info = { @@ -1718,6 +1721,7 @@ static void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) aic->has_dma = true; aic->mem_size = 0x2000; aic->has_dma64 = true; + aic->dma_addr_lo_mask = 0xffffffff; } static const TypeInfo aspeed_2700_i2c_info = { -- 2.43.0
