diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index 93b8fd1661..c48fa2050b 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -116,8 +116,6 @@ static uint64_t aspeed_i2c_bus_old_read(AspeedI2CBus *bus, hwaddr offset, value = -1; break; } - - value = extract64(bus->dma_dram_offset, 0, 32); break; case A_I2CD_DMA_LEN: if (!aic->has_dma) { @@ -221,6 +219,64 @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus) return SHARED_ARRAY_FIELD_EX32(bus->regs, R_I2CD_CMD, TX_STATE); } +/* + * The AST2700 support the maximum DRAM size is 8 GB. + * The DRAM offset range is from 0x0_0000_0000 to + * 0x1_FFFF_FFFF and it is enough to use bits [33:0] + * saving the dram offset. + * Therefore, save the high part physical address bit[1:0] + * of Tx/Rx buffer address as dma_dram_offset bit[33:32]. + */ +static void aspeed_i2c_set_tx_dma_dram_offset(AspeedI2CBus *bus) +{ + AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller); + uint32_t value; + + assert(aic->has_dma); + + if (aspeed_i2c_is_new_mode(bus->controller)) { + 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)); + if (!aic->has_dma64) { + value = bus->regs[R_I2CM_DMA_TX_ADDR_HI]; + bus->dma_dram_offset = + deposit64(bus->dma_dram_offset, 32, 32, + extract32(value, 0, 2)); + } + } else { + value = bus->regs[R_I2CD_DMA_ADDR]; + bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, + value & 0x3ffffffc); + } +} + +static void aspeed_i2c_set_rx_dma_dram_offset(AspeedI2CBus *bus) +{ + AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller); + uint32_t value; + + assert(aic->has_dma); + + if (aspeed_i2c_is_new_mode(bus->controller)) { + 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)); + if (!aic->has_dma64) { + value = bus->regs[R_I2CM_DMA_RX_ADDR_HI]; + bus->dma_dram_offset = + deposit64(bus->dma_dram_offset, 32, 32, + extract32(value, 0, 2)); + } + } else { + value = bus->regs[R_I2CD_DMA_ADDR]; + bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, + value & 0x3ffffffc); + } +} + static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data) { MemTxResult result; @@ -270,6 +326,7 @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus) if (aspeed_i2c_is_new_mode(bus->controller)) { ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, TX_LEN, 0); } + aspeed_i2c_set_tx_dma_dram_offset(bus); while (bus->regs[reg_dma_len]) { uint8_t data; ret = aspeed_i2c_dma_read(bus, &data); @@ -335,6 +392,7 @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus) ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, RX_LEN, 0); } + aspeed_i2c_set_rx_dma_dram_offset(bus); while (bus->regs[reg_dma_len]) { MemTxResult result; @@ -401,6 +459,7 @@ static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus) } else if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_DMA_EN)) { uint8_t data; + aspeed_i2c_set_tx_dma_dram_offset(bus); aspeed_i2c_dma_read(bus, &data); return data; } else { @@ -657,16 +716,10 @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, case A_I2CM_DMA_TX_ADDR: bus->regs[R_I2CM_DMA_TX_ADDR] = FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR); - bus->dma_dram_offset = - deposit64(bus->dma_dram_offset, 0, 32, - FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR)); break; case A_I2CM_DMA_RX_ADDR: bus->regs[R_I2CM_DMA_RX_ADDR] = FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR); - bus->dma_dram_offset = - deposit64(bus->dma_dram_offset, 0, 32, - FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR)); break; case A_I2CM_DMA_LEN: w1t = FIELD_EX32(value, I2CM_DMA_LEN, RX_BUF_LEN_W1T) || @@ -748,15 +801,6 @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, qemu_log_mask(LOG_UNIMP, "%s: Slave mode DMA TX is not implemented\n", __func__); break; - - /* - * The AST2700 support the maximum DRAM size is 8 GB. - * The DRAM offset range is from 0x0_0000_0000 to - * 0x1_FFFF_FFFF and it is enough to use bits [33:0] - * saving the dram offset. - * Therefore, save the high part physical address bit[1:0] - * of Tx/Rx buffer address as dma_dram_offset bit[33:32]. - */ case A_I2CM_DMA_TX_ADDR_HI: if (!aic->has_dma64) { qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA 64 bits support\n", @@ -766,8 +810,6 @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CM_DMA_TX_ADDR_HI] = FIELD_EX32(value, I2CM_DMA_TX_ADDR_HI, ADDR_HI); - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32, - extract32(value, 0, 2)); break; case A_I2CM_DMA_RX_ADDR_HI: if (!aic->has_dma64) { @@ -778,8 +820,6 @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CM_DMA_RX_ADDR_HI] = FIELD_EX32(value, I2CM_DMA_RX_ADDR_HI, ADDR_HI); - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32, - extract32(value, 0, 2)); break; case A_I2CS_DMA_TX_ADDR_HI: qemu_log_mask(LOG_UNIMP, @@ -795,8 +835,6 @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CS_DMA_RX_ADDR_HI] = FIELD_EX32(value, I2CS_DMA_RX_ADDR_HI, ADDR_HI); - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32, - extract32(value, 0, 2)); break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", @@ -887,9 +925,6 @@ static void aspeed_i2c_bus_old_write(AspeedI2CBus *bus, hwaddr offset, qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__); break; } - - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - value & 0x3ffffffc); break; case A_I2CD_DMA_LEN: