|
@@ -114,7 +114,10 @@ static uint64_t aspeed_i2c_bus_old_read(AspeedI2CBus *bus, hwaddr offset,
|
|
|
if (!aic->has_dma) {
|
|
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
|
|
|
value = -1;
|
|
|
+ break;
|
|
|
}
|
|
|
+
|
|
|
+ value = extract64(bus->dma_dram_offset, 0, 32);
|
|
|
break;
|
|
|
case A_I2CD_DMA_LEN:
|
|
|
if (!aic->has_dma) {
|
|
@@ -150,9 +153,7 @@ static uint64_t aspeed_i2c_bus_new_read(AspeedI2CBus *bus, hwaddr offset,
|
|
|
case A_I2CM_DMA_TX_ADDR:
|
|
|
case A_I2CM_DMA_RX_ADDR:
|
|
|
case A_I2CM_DMA_LEN_STS:
|
|
|
- case A_I2CC_DMA_ADDR:
|
|
|
case A_I2CC_DMA_LEN:
|
|
|
-
|
|
|
case A_I2CS_DEV_ADDR:
|
|
|
case A_I2CS_DMA_RX_ADDR:
|
|
|
case A_I2CS_DMA_LEN:
|
|
@@ -161,6 +162,9 @@ static uint64_t aspeed_i2c_bus_new_read(AspeedI2CBus *bus, hwaddr offset,
|
|
|
case A_I2CS_DMA_LEN_STS:
|
|
|
/* Value is already set, don't do anything. */
|
|
|
break;
|
|
|
+ case A_I2CC_DMA_ADDR:
|
|
|
+ value = extract64(bus->dma_dram_offset, 0, 32);
|
|
|
+ break;
|
|
|
case A_I2CS_INTR_STS:
|
|
|
break;
|
|
|
case A_I2CM_CMD:
|
|
@@ -210,18 +214,18 @@ static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data)
|
|
|
{
|
|
|
MemTxResult result;
|
|
|
AspeedI2CState *s = bus->controller;
|
|
|
- uint32_t reg_dma_addr = aspeed_i2c_bus_dma_addr_offset(bus);
|
|
|
uint32_t reg_dma_len = aspeed_i2c_bus_dma_len_offset(bus);
|
|
|
|
|
|
- result = address_space_read(&s->dram_as, bus->regs[reg_dma_addr],
|
|
|
+ result = address_space_read(&s->dram_as, bus->dma_dram_offset,
|
|
|
MEMTXATTRS_UNSPECIFIED, data, 1);
|
|
|
if (result != MEMTX_OK) {
|
|
|
- qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM read failed @%08x\n",
|
|
|
- __func__, bus->regs[reg_dma_addr]);
|
|
|
+ qemu_log_mask(LOG_GUEST_ERROR,
|
|
|
+ "%s: DRAM read failed @%" PRIx64 "\n",
|
|
|
+ __func__, bus->dma_dram_offset);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- bus->regs[reg_dma_addr]++;
|
|
|
+ bus->dma_dram_offset++;
|
|
|
bus->regs[reg_dma_len]--;
|
|
|
return 0;
|
|
|
}
|
|
@@ -291,7 +295,6 @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
|
|
|
uint32_t reg_pool_ctrl = aspeed_i2c_bus_pool_ctrl_offset(bus);
|
|
|
uint32_t reg_byte_buf = aspeed_i2c_bus_byte_buf_offset(bus);
|
|
|
uint32_t reg_dma_len = aspeed_i2c_bus_dma_len_offset(bus);
|
|
|
- uint32_t reg_dma_addr = aspeed_i2c_bus_dma_addr_offset(bus);
|
|
|
int pool_rx_count = SHARED_ARRAY_FIELD_EX32(bus->regs, reg_pool_ctrl,
|
|
|
RX_SIZE) + 1;
|
|
|
|
|
@@ -323,14 +326,17 @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
|
|
|
data = i2c_recv(bus->bus);
|
|
|
trace_aspeed_i2c_bus_recv("DMA", bus->regs[reg_dma_len],
|
|
|
bus->regs[reg_dma_len], data);
|
|
|
- result = address_space_write(&s->dram_as, bus->regs[reg_dma_addr],
|
|
|
+
|
|
|
+ result = address_space_write(&s->dram_as, bus->dma_dram_offset,
|
|
|
MEMTXATTRS_UNSPECIFIED, &data, 1);
|
|
|
if (result != MEMTX_OK) {
|
|
|
- qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed @%08x\n",
|
|
|
- __func__, bus->regs[reg_dma_addr]);
|
|
|
+ qemu_log_mask(LOG_GUEST_ERROR,
|
|
|
+ "%s: DRAM write failed @%" PRIx64 "\n",
|
|
|
+ __func__, bus->dma_dram_offset);
|
|
|
return;
|
|
|
}
|
|
|
- bus->regs[reg_dma_addr]++;
|
|
|
+
|
|
|
+ bus->dma_dram_offset++;
|
|
|
bus->regs[reg_dma_len]--;
|
|
|
/* In new mode, keep track of how many bytes we RXed */
|
|
|
if (aspeed_i2c_is_new_mode(bus->controller)) {
|
|
@@ -636,14 +642,18 @@ 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->regs[R_I2CC_DMA_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));
|
|
|
bus->regs[R_I2CC_DMA_LEN] = ARRAY_FIELD_EX32(bus->regs, I2CM_DMA_LEN,
|
|
|
TX_BUF_LEN) + 1;
|
|
|
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_I2CC_DMA_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));
|
|
|
bus->regs[R_I2CC_DMA_LEN] = ARRAY_FIELD_EX32(bus->regs, I2CM_DMA_LEN,
|
|
|
RX_BUF_LEN) + 1;
|
|
|
break;
|
|
@@ -811,7 +821,8 @@ static void aspeed_i2c_bus_old_write(AspeedI2CBus *bus, hwaddr offset,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- bus->regs[R_I2CD_DMA_ADDR] = value & 0x3ffffffc;
|
|
|
+ bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32,
|
|
|
+ value & 0x3ffffffc);
|
|
|
break;
|
|
|
|
|
|
case A_I2CD_DMA_LEN:
|
|
@@ -983,6 +994,7 @@ static const VMStateDescription aspeed_i2c_bus_vmstate = {
|
|
|
.fields = (const VMStateField[]) {
|
|
|
VMSTATE_UINT32_ARRAY(regs, AspeedI2CBus, ASPEED_I2C_NEW_NUM_REG),
|
|
|
VMSTATE_UINT8_ARRAY(pool, AspeedI2CBus, ASPEED_I2C_BUS_POOL_SIZE),
|
|
|
+ VMSTATE_UINT64(dma_dram_offset, AspeedI2CBus),
|
|
|
VMSTATE_END_OF_LIST()
|
|
|
}
|
|
|
};
|
|
@@ -1188,8 +1200,9 @@ static int aspeed_i2c_bus_new_slave_event(AspeedI2CBus *bus,
|
|
|
return -1;
|
|
|
}
|
|
|
ARRAY_FIELD_DP32(bus->regs, I2CS_DMA_LEN_STS, RX_LEN, 0);
|
|
|
- bus->regs[R_I2CC_DMA_ADDR] =
|
|
|
- ARRAY_FIELD_EX32(bus->regs, I2CS_DMA_RX_ADDR, ADDR);
|
|
|
+ bus->dma_dram_offset =
|
|
|
+ deposit64(bus->dma_dram_offset, 0, 32,
|
|
|
+ ARRAY_FIELD_EX32(bus->regs, I2CS_DMA_RX_ADDR, ADDR));
|
|
|
bus->regs[R_I2CC_DMA_LEN] =
|
|
|
ARRAY_FIELD_EX32(bus->regs, I2CS_DMA_LEN, RX_BUF_LEN) + 1;
|
|
|
i2c_ack(bus->bus);
|
|
@@ -1255,10 +1268,10 @@ static int aspeed_i2c_bus_slave_event(I2CSlave *slave, enum i2c_event event)
|
|
|
static void aspeed_i2c_bus_new_slave_send_async(AspeedI2CBus *bus, uint8_t data)
|
|
|
{
|
|
|
assert(address_space_write(&bus->controller->dram_as,
|
|
|
- bus->regs[R_I2CC_DMA_ADDR],
|
|
|
+ bus->dma_dram_offset,
|
|
|
MEMTXATTRS_UNSPECIFIED, &data, 1) == MEMTX_OK);
|
|
|
|
|
|
- bus->regs[R_I2CC_DMA_ADDR]++;
|
|
|
+ bus->dma_dram_offset++;
|
|
|
bus->regs[R_I2CC_DMA_LEN]--;
|
|
|
ARRAY_FIELD_DP32(bus->regs, I2CS_DMA_LEN_STS, RX_LEN,
|
|
|
ARRAY_FIELD_EX32(bus->regs, I2CS_DMA_LEN_STS, RX_LEN) + 1);
|