:p
atchew
Login
This series extends the AST1040 SoC model by adding support for several peripherals that are compatible with existing AST2700 controller models. The AST1040 shares a number of peripheral IP blocks with the AST2700, allowing the existing QEMU models to be reused with minimal changes. This series adds support for ADC, PECI, GPIO, SGPIO, I2C, and watchdog controllers, and updates the AST1040 EVB machine to instantiate onboard I2C devices for validation. For I2C support, a new AST1040 I2C type is introduced. The model inherits the AST2700 I2C architecture, including DMA support and 64-bit DMA address registers, while constraining DMA accesses to the 16 MiB HyperRAM address space available on AST1040. Depends on: https://github.com/legoater/qemu.git (branch: aspeed-next) v1: 1. Support ADC, GPIO, SGPIO, I2C and PECI v2: 1. Address review feedback. 2. Fix issues reported during review. Jamin Lin (10): hw/i2c/aspeed_i2c: Introduce dma_addr_lo_mask to unify DMA address handling hw/i2c/aspeed_i2c: Increase AST2700 buffer mode size and adjust offset hw/arm/aspeed_ast1040: Reuse AST2700 ADC model hw/arm/aspeed_ast1040: Introduce PECI support hw/arm/aspeed_ast1040: Reuse AST2700 GPIO controller model hw/arm/aspeed_ast1040: Add SGPIO controller support hw/i2c/aspeed_i2c: Introduce AST1040 I2C model hw/arm/aspeed_ast1040: Introduce I2C support hw/arm/aspeed_ast1040_evb: Introduce onboard I2C device hw/arm/aspeed_ast1040: Reuse AST2700 watchdog models include/hw/i2c/aspeed_i2c.h | 8 ++- hw/arm/aspeed_ast1040.c | 97 +++++++++++++++++++++++++++++----- hw/arm/aspeed_ast1040_evb.c | 18 +++++++ hw/i2c/aspeed_i2c.c | 101 ++++++++++++++++++++++++------------ 4 files changed, 175 insertions(+), 49 deletions(-) -- 2.43.0
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. Fixes: 1809ab6a67359e0876981cd05d2a50b2843eabad ("hw/i2c/aspeed: Add AST2700 support") Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ 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 = @@ -XXX,XX +XXX,XX @@ 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); } } @@ -XXX,XX +XXX,XX @@ 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 = @@ -XXX,XX +XXX,XX @@ 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); } } @@ -XXX,XX +XXX,XX @@ 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) || @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_class_init(ObjectClass *klass, const void *data) 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)) { @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 qemu_irq aspeed_2600_i2c_bus_get_irq(AspeedI2CBus *bus) @@ -XXX,XX +XXX,XX @@ 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 void aspeed_1030_i2c_class_init(ObjectClass *klass, const void *data) @@ -XXX,XX +XXX,XX @@ 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 void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) @@ -XXX,XX +XXX,XX @@ 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_i2c_types[] = { -- 2.43.0
Update the AST2700 I2C buffer mode configuration to match the latest firmware definition: - Increase buffer mode pool size from 0x20 to 0x40 - Adjust buffer mode base offset to 0x1c0 Since the buffer mode region size changes, the migration state layout is also modified. Bump the VMState version numbers to prevent incompatible migration between old and new machine states. Fixes: 1809ab6a67359e0876981cd05d2a50b2843eabad ("hw/i2c/aspeed: Add AST2700 support") Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- include/hw/i2c/aspeed_i2c.h | 2 +- hw/i2c/aspeed_i2c.c | 46 ++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) #define ASPEED_I2C_NR_BUSSES 16 #define ASPEED_I2C_SHARE_POOL_SIZE 0x800 -#define ASPEED_I2C_BUS_POOL_SIZE 0x20 +#define ASPEED_I2C_BUS_POOL_SIZE 0x40 #define ASPEED_I2C_NEW_NUM_REG (0xa0 >> 2) #define A_I2CD_M_STOP_CMD BIT(5) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_i2c_bus_pool_ops = { static const VMStateDescription aspeed_i2c_bus_vmstate = { .name = TYPE_ASPEED_I2C, - .version_id = 7, - .minimum_version_id = 6, + .version_id = 8, + .minimum_version_id = 7, .fields = (const VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, AspeedI2CBus, ASPEED_I2C_NEW_NUM_REG), VMSTATE_UINT32_V(pending_intr_sts, AspeedI2CBus, 7), @@ -XXX,XX +XXX,XX @@ static const VMStateDescription aspeed_i2c_bus_vmstate = { static const VMStateDescription aspeed_i2c_vmstate = { .name = TYPE_ASPEED_I2C, - .version_id = 3, - .minimum_version_id = 3, + .version_id = 4, + .minimum_version_id = 4, .fields = (const VMStateField[]) { VMSTATE_UINT32(intr_status, AspeedI2CState), VMSTATE_STRUCT_ARRAY(busses, AspeedI2CState, @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_instance_init(Object *obj) * Address Definitions (AST2700) * 0x000 ... 0x0FF: Global Register * 0x100 ... 0x19F: Device 0 - * 0x1A0 ... 0x1BF: Device 0 buffer + * 0x1C0 ... 0x1FF: Device 0 buffer * 0x200 ... 0x29F: Device 1 - * 0x2A0 ... 0x2BF: Device 1 buffer + * 0x2C0 ... 0x2FF: Device 1 buffer * 0x300 ... 0x39F: Device 2 - * 0x3A0 ... 0x3BF: Device 2 buffer + * 0x3C0 ... 0x3FF: Device 2 buffer * 0x400 ... 0x49F: Device 3 - * 0x4A0 ... 0x4BF: Device 3 buffer + * 0x4C0 ... 0x4FF: Device 3 buffer * 0x500 ... 0x59F: Device 4 - * 0x5A0 ... 0x5BF: Device 4 buffer + * 0x5C0 ... 0x5FF: Device 4 buffer * 0x600 ... 0x69F: Device 5 - * 0x6A0 ... 0x6BF: Device 5 buffer + * 0x6C0 ... 0x6FF: Device 5 buffer * 0x700 ... 0x79F: Device 6 - * 0x7A0 ... 0x7BF: Device 6 buffer + * 0x7C0 ... 0x7FF: Device 6 buffer * 0x800 ... 0x89F: Device 7 - * 0x8A0 ... 0x8BF: Device 7 buffer + * 0x8C0 ... 0x8FF: Device 7 buffer * 0x900 ... 0x99F: Device 8 - * 0x9A0 ... 0x9BF: Device 8 buffer + * 0x9C0 ... 0x9FF: Device 8 buffer * 0xA00 ... 0xA9F: Device 9 - * 0xAA0 ... 0xABF: Device 9 buffer + * 0xAC0 ... 0xAFF: Device 9 buffer * 0xB00 ... 0xB9F: Device 10 - * 0xBA0 ... 0xBBF: Device 10 buffer + * 0xBC0 ... 0xBFF: Device 10 buffer * 0xC00 ... 0xC9F: Device 11 - * 0xCA0 ... 0xCBF: Device 11 buffer + * 0xCC0 ... 0xCFF: Device 11 buffer * 0xD00 ... 0xD9F: Device 12 - * 0xDA0 ... 0xDBF: Device 12 buffer + * 0xDC0 ... 0xDFF: Device 12 buffer * 0xE00 ... 0xE9F: Device 13 - * 0xEA0 ... 0xEBF: Device 13 buffer + * 0xEC0 ... 0xEFF: Device 13 buffer * 0xF00 ... 0xF9F: Device 14 - * 0xFA0 ... 0xFBF: Device 14 buffer + * 0xFC0 ... 0xFFF: Device 14 buffer * 0x1000 ... 0x109F: Device 15 - * 0x10A0 ... 0x10BF: Device 15 buffer + * 0x10C0 ... 0x10BF: Device 15 buffer */ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) { @@ -XXX,XX +XXX,XX @@ static void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) aic->reg_gap_size = 0x60; aic->gap = -1; /* no gap */ aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq; - aic->pool_size = 0x20; - aic->pool_gap_size = 0xe0; - aic->pool_base = 0x1a0; + aic->pool_size = 0x40; + aic->pool_gap_size = 0xc0; + aic->pool_base = 0x1c0; aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; aic->has_dma = true; aic->mem_size = 0x2000; -- 2.43.0
Instead of introducing a dedicated TYPE_ASPEED_1040_ADC model, initialize the existing AST2700 ADC device directly for AST1040. This avoids unnecessary duplication and keeps the codebase simpler and easier to maintain. Add ADC device initialization and realization support to the AST1040 SoC model using TYPE_ASPEED_2700_ADC. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM); } + object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); + object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) aspeed_soc_ast1040_get_irq(s, uart)); } + /* ADC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0, + sc->memmap[ASPEED_DEV_ADC]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_ADC)); + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
Introduce PECI support for the AST1040 SoC model. This change adds the PECI MMIO region and IRQ mapping, initializes the PECI device instance, and realizes the controller during SoC initialization. The PECI controller is mapped at 0x74C1F000 and connected to IRQ 164. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast1040_memmap[] = { [ASPEED_DEV_SGPIOM0] = 0x74C0C000, [ASPEED_DEV_SGPIOM1] = 0x74C0D000, [ASPEED_DEV_I2C] = 0x74C0F000, + [ASPEED_DEV_PECI] = 0x74C1F000, [ASPEED_DEV_I3C] = 0x74C20000, [ASPEED_DEV_UART0] = 0x74C33000, [ASPEED_DEV_UART1] = 0x74C33100, @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast1040_irqmap[] = { [ASPEED_DEV_UART11] = 146, [ASPEED_DEV_UART12] = 147, [ASPEED_DEV_JTAG0] = 162, + [ASPEED_DEV_PECI] = 164, }; static qemu_irq aspeed_soc_ast1040_get_irq(AspeedSoCState *s, int dev) @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) } object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); + object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_ADC)); + /* PECI */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->peci), 0, + sc->memmap[ASPEED_DEV_PECI]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_PECI)); + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
The AST1040 GPIO controller is compatible with the AST2700 GPIO controller implementation. Reuse the existing "aspeed.gpio-ast2700" device model for AST1040 instead of introducing a separate implementation. Add the GPIO device initialization, MMIO mapping, and IRQ wiring for the AST1040 SoC model. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); + object_initialize_child(obj, "gpio", &s->gpio, "aspeed.gpio-ast2700"); object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0, aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_PECI)); + /* GPIO */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0, + sc->memmap[ASPEED_DEV_GPIO]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_GPIO)); + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
The AST1040 SGPIO controller is compatible with the AST2700 SGPIO controller implementation. AST1040 contains two SGPIO controllers, so reuse the existing "aspeed.sgpio-ast2700" device model instead of keeping them as unimplemented devices. MMIO mapping: - SGPIOM0 : 0x74C0C000 - SGPIOM1 : 0x74C0D000 IRQ mapping: - SGPIOM0 : IRQ 85 - SGPIOM1 : IRQ 88 Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast1040_irqmap[] = { [ASPEED_DEV_ADC] = 80, [ASPEED_DEV_GPIO] = 82, [ASPEED_DEV_SGPIOM0] = 85, + [ASPEED_DEV_SGPIOM1] = 88, [ASPEED_DEV_TIMER1] = 92, [ASPEED_DEV_I3C] = 96, /* 96 ~ 103 */ [ASPEED_DEV_WDT] = 112, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); object_initialize_child(obj, "gpio", &s->gpio, "aspeed.gpio-ast2700"); + for (i = 0; i < sc->sgpio_num; i++) { + object_initialize_child(obj, "sgpio[*]", &s->sgpiom[i], + "aspeed.sgpio-ast2700"); + } object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE); - object_initialize_child(obj, "sgpiom[0]", &s->sgpiom[0], - TYPE_UNIMPLEMENTED_DEVICE); - object_initialize_child(obj, "sgpiom[1]", &s->sgpiom[1], - TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "jtag[0]", &s->jtag[0], TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "jtag[1]", &s->jtag[1], @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_GPIO)); + /* SGPIO */ + for (i = 0; i < sc->sgpio_num; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sgpiom[i]), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sgpiom[i]), 0, + sc->memmap[ASPEED_DEV_SGPIOM0 + i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sgpiom[i]), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_SGPIOM0 + i)); + } + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) "aspeed.udc", sc->memmap[ASPEED_DEV_UDC], 0x4000); - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->sgpiom[0]), - "aspeed.sgpiom0", - sc->memmap[ASPEED_DEV_SGPIOM0], 0x1000); - - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->sgpiom[1]), - "aspeed.sgpiom1", - sc->memmap[ASPEED_DEV_SGPIOM1], 0x1000); - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->jtag[0]), "aspeed.jtag0", sc->memmap[ASPEED_DEV_JTAG0], 0x100); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_class_init(ObjectClass *klass, const void *data) sc->sram_size[0] = 128 * KiB; sc->sram_size[1] = 16 * MiB; /* Hyper RAM */ sc->uarts_num = 13; + sc->sgpio_num = 2; sc->uarts_base = ASPEED_DEV_UART0; sc->irqmap = aspeed_soc_ast1040_irqmap; sc->memmap = aspeed_soc_ast1040_memmap; -- 2.43.0
Introduce the AST1040 I2C controller model. The AST1040 I2C controller is compatible with the AST2700 I2C controller, including DMA support and the 64-bit DMA address registers. Set has_dma64 so firmware can access the high address register and program it to zero, as the CM4 CPU only supports 32-bit addressing. Since AST1040 has 16MB HyperRAM, limit the DMA low address mask to 0x00ffffff. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- include/hw/i2c/aspeed_i2c.h | 1 + hw/i2c/aspeed_i2c.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ #define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500" #define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600" #define TYPE_ASPEED_1030_I2C TYPE_ASPEED_I2C "-ast1030" +#define TYPE_ASPEED_1040_I2C TYPE_ASPEED_I2C "-ast1040" #define TYPE_ASPEED_2700_I2C TYPE_ASPEED_I2C "-ast2700" OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static void aspeed_1030_i2c_class_init(ObjectClass *klass, const void *data) aic->dma_addr_lo_mask = 0x7fffffff; } +static void aspeed_1040_i2c_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass); + + dc->desc = "ASPEED 1040 I2C Controller"; + + /* + * AST1040 reuses the AST2700 I2C controller implementation since + * the AST1040 is compatible with AST2700. The only difference + * is that AST1040 HyperRAM is limited to 16 MiB, so the DMA low + * address mask is restricted accordingly. + */ + aic->num_busses = 16; + aic->reg_size = 0xa0; + aic->reg_gap_size = 0x60; + aic->gap = -1; /* no gap */ + aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq; + aic->pool_size = 0x40; + aic->pool_gap_size = 0xc0; + aic->pool_base = 0x1c0; + aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; + aic->has_dma = true; + aic->mem_size = 0x2000; + aic->has_dma64 = true; + aic->dma_addr_lo_mask = 0x00ffffff; +} + static void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_i2c_types[] = { .parent = TYPE_ASPEED_I2C, .class_init = aspeed_1030_i2c_class_init, }, + { + .name = TYPE_ASPEED_1040_I2C, + .parent = TYPE_ASPEED_I2C, + .class_init = aspeed_1040_i2c_class_init, + }, { .name = TYPE_ASPEED_2400_I2C, .parent = TYPE_ASPEED_I2C, -- 2.43.0
Introduce I2C controller support for the AST1040 SoC model. The I2C model type is selected from the SoC type name, allowing the AST1040 SoC to use the corresponding aspeed.i2c-ast1040 model. The I2C controller is mapped at 0x74C0F000 and uses IRQs 64 - 77, with one IRQ assigned per I2C bus. The controller DRAM link is connected to SRAM1 (HyperRAM) for DMA support. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- hw/arm/aspeed_ast1040.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "sgpio[*]", &s->sgpiom[i], "aspeed.sgpio-ast2700"); } + object_initialize_child(obj, "i2c", &s->i2c, TYPE_ASPEED_1040_I2C); object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_SGPIOM0 + i)); } + /* I2C */ + object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(&s->sram[1]), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0, + sc->memmap[ASPEED_DEV_I2C]); + for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) { + qemu_irq irq = qdev_get_gpio_in(DEVICE(&a->armv7m), + sc->irqmap[ASPEED_DEV_I2C] + i); + /* The AST1040 I2C controller has one IRQ per bus. */ + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq); + } + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
Introduce onboard I2C device initialization for the AST1040 EVB model. This change adds the initial onboard I2C device setup flow and instantiates a 24C08 SMBus EEPROM device connected to I2C bus 0, matching the current AST1040 EVB hardware design. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- hw/arm/aspeed_ast1040_evb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/hw/arm/aspeed_ast1040_evb.c b/hw/arm/aspeed_ast1040_evb.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040_evb.c +++ b/hw/arm/aspeed_ast1040_evb.c @@ -XXX,XX +XXX,XX @@ #include "hw/arm/aspeed_soc.h" #include "hw/core/qdev-clock.h" #include "system/system.h" +#include "hw/i2c/smbus_eeprom.h" #define AST1040_INTERNAL_FLASH_SIZE (4 * MiB) /* Main SYSCLK frequency in Hz (400MHz) */ @@ -XXX,XX +XXX,XX @@ static void aspeed_bic_machine_init(MachineState *machine) aspeed_connect_serial_hds_to_uarts(bmc); qdev_realize(DEVICE(bmc->soc), NULL, &error_abort); + if (amc->i2c_init) { + amc->i2c_init(bmc); + } + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0, AST1040_INTERNAL_FLASH_SIZE); } +static void ast1040_evb_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = bmc->soc; + + /* U10 24C08 connects to SDA/SCL Group 1 by default */ + uint8_t *eeprom_buf = g_malloc0(32 * KiB); + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50, eeprom_buf); + + /* U11 LM75 connects to SDA/SCL Group 2 by default */ + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4d); +} + static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, const void *data) { @@ -XXX,XX +XXX,XX @@ static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, amc->hw_strap1 = 0; amc->hw_strap2 = 0; mc->init = aspeed_bic_machine_init; + amc->i2c_init = ast1040_evb_i2c_init; mc->default_ram_size = 0; amc->macs_mask = 0; amc->uart_default = ASPEED_DEV_UART12; -- 2.43.0
Instantiate and realize the watchdog models for the AST1040 SoC. The AST1040 watchdog controller is compatible with the AST2700 watchdog controller, so reuse the existing AST2700 watchdog model. Configure the AST1040 SoC with 8 watchdog instances and map them to their corresponding MMIO regions. The first watchdog controller (WDT0) is located at 0x74c37000, with subsequent watchdogs placed according to the controller register space size. Each watchdog is linked to the SCU device before realization to provide the required reset and system control interactions. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) } object_initialize_child(obj, "i2c", &s->i2c, TYPE_ASPEED_1040_I2C); + for (i = 0; i < sc->wdts_num; i++) { + object_initialize_child(obj, "wdt[*]", &s->wdt[i], + "aspeed.wdt-ast2700"); + } + object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq); } + /* Watch dog */ + for (i = 0; i < sc->wdts_num; i++) { + AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]); + hwaddr wdt_offset = sc->memmap[ASPEED_DEV_WDT] + i * awc->iosize; + + object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset); + } + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_class_init(ObjectClass *klass, const void *data) sc->sram_size[1] = 16 * MiB; /* Hyper RAM */ sc->uarts_num = 13; sc->sgpio_num = 2; + sc->wdts_num = 8; sc->uarts_base = ASPEED_DEV_UART0; sc->irqmap = aspeed_soc_ast1040_irqmap; sc->memmap = aspeed_soc_ast1040_memmap; -- 2.43.0
This series extends the AST1040 SoC model by adding support for several peripherals that are compatible with existing AST2700 controller models. The AST1040 shares a number of peripheral IP blocks with the AST2700, allowing the existing QEMU models to be reused with minimal changes. This series adds support for ADC, PECI, GPIO, SGPIO, I2C, and watchdog controllers, and updates the AST1040 EVB machine to instantiate onboard I2C devices for validation. For I2C support, a new AST1040 I2C type is introduced. The model inherits the AST2700 I2C architecture, including DMA support and 64-bit DMA address registers, while constraining DMA accesses to the 16 MiB HyperRAM address space available on AST1040. Depends on: https://github.com/legoater/qemu.git (branch: aspeed-next) v1: 1. Support ADC, GPIO, SGPIO, I2C and PECI v2: 1. Address review feedback. 2. Fix issues reported during review. 3. Update i2c bus number to 14. Jamin Lin (10): hw/i2c/aspeed_i2c: Introduce dma_addr_lo_mask to unify DMA address handling hw/i2c/aspeed_i2c: Increase AST2700 buffer mode size and adjust offset hw/arm/aspeed_ast1040: Reuse AST2700 ADC model hw/arm/aspeed_ast1040: Introduce PECI support hw/arm/aspeed_ast1040: Reuse AST2700 GPIO controller model hw/arm/aspeed_ast1040: Add SGPIO controller support hw/i2c/aspeed_i2c: Introduce AST1040 I2C model hw/arm/aspeed_ast1040: Introduce I2C support hw/arm/aspeed_ast1040_evb: Introduce onboard I2C device hw/arm/aspeed_ast1040: Reuse AST2700 watchdog models include/hw/i2c/aspeed_i2c.h | 8 ++- hw/arm/aspeed_ast1040.c | 97 ++++++++++++++++++++++++++++----- hw/arm/aspeed_ast1040_evb.c | 15 ++++++ hw/i2c/aspeed_i2c.c | 103 ++++++++++++++++++++++++------------ 4 files changed, 173 insertions(+), 50 deletions(-) -- 2.43.0
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. Fixes: 1809ab6a67359e0876981cd05d2a50b2843eabad ("hw/i2c/aspeed: Add AST2700 support") Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- include/hw/i2c/aspeed_i2c.h | 5 +---- hw/i2c/aspeed_i2c.c | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ 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 = @@ -XXX,XX +XXX,XX @@ 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); } } @@ -XXX,XX +XXX,XX @@ 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 = @@ -XXX,XX +XXX,XX @@ 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); } } @@ -XXX,XX +XXX,XX @@ 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) || @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CS_DEV_ADDR] = value; break; case A_I2CS_DMA_RX_ADDR: - bus->regs[R_I2CS_DMA_RX_ADDR] = value; + bus->regs[R_I2CS_DMA_RX_ADDR] = value & aic->dma_addr_lo_mask; break; case A_I2CS_DMA_LEN: if (FIELD_EX32(value, I2CS_DMA_LEN, RX_BUF_LEN_W1T)) { @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_class_init(ObjectClass *klass, const void *data) 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)) { @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 qemu_irq aspeed_2600_i2c_bus_get_irq(AspeedI2CBus *bus) @@ -XXX,XX +XXX,XX @@ 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 void aspeed_1030_i2c_class_init(ObjectClass *klass, const void *data) @@ -XXX,XX +XXX,XX @@ 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 void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) @@ -XXX,XX +XXX,XX @@ 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_i2c_types[] = { -- 2.43.0
Update the AST2700 I2C buffer mode configuration to match the latest firmware definition: - Increase buffer mode pool size from 0x20 to 0x40 - Adjust buffer mode base offset to 0x1c0 Since the buffer mode region size changes, the migration state layout is also modified. Bump the VMState version numbers to prevent incompatible migration between old and new machine states. Fixes: 1809ab6a67359e0876981cd05d2a50b2843eabad ("hw/i2c/aspeed: Add AST2700 support") Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- include/hw/i2c/aspeed_i2c.h | 2 +- hw/i2c/aspeed_i2c.c | 46 ++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) #define ASPEED_I2C_NR_BUSSES 16 #define ASPEED_I2C_SHARE_POOL_SIZE 0x800 -#define ASPEED_I2C_BUS_POOL_SIZE 0x20 +#define ASPEED_I2C_BUS_POOL_SIZE 0x40 #define ASPEED_I2C_NEW_NUM_REG (0xa0 >> 2) #define A_I2CD_M_STOP_CMD BIT(5) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_i2c_bus_pool_ops = { static const VMStateDescription aspeed_i2c_bus_vmstate = { .name = TYPE_ASPEED_I2C, - .version_id = 7, - .minimum_version_id = 6, + .version_id = 8, + .minimum_version_id = 8, .fields = (const VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, AspeedI2CBus, ASPEED_I2C_NEW_NUM_REG), VMSTATE_UINT32_V(pending_intr_sts, AspeedI2CBus, 7), @@ -XXX,XX +XXX,XX @@ static const VMStateDescription aspeed_i2c_bus_vmstate = { static const VMStateDescription aspeed_i2c_vmstate = { .name = TYPE_ASPEED_I2C, - .version_id = 3, - .minimum_version_id = 3, + .version_id = 4, + .minimum_version_id = 4, .fields = (const VMStateField[]) { VMSTATE_UINT32(intr_status, AspeedI2CState), VMSTATE_STRUCT_ARRAY(busses, AspeedI2CState, @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_instance_init(Object *obj) * Address Definitions (AST2700) * 0x000 ... 0x0FF: Global Register * 0x100 ... 0x19F: Device 0 - * 0x1A0 ... 0x1BF: Device 0 buffer + * 0x1C0 ... 0x1FF: Device 0 buffer * 0x200 ... 0x29F: Device 1 - * 0x2A0 ... 0x2BF: Device 1 buffer + * 0x2C0 ... 0x2FF: Device 1 buffer * 0x300 ... 0x39F: Device 2 - * 0x3A0 ... 0x3BF: Device 2 buffer + * 0x3C0 ... 0x3FF: Device 2 buffer * 0x400 ... 0x49F: Device 3 - * 0x4A0 ... 0x4BF: Device 3 buffer + * 0x4C0 ... 0x4FF: Device 3 buffer * 0x500 ... 0x59F: Device 4 - * 0x5A0 ... 0x5BF: Device 4 buffer + * 0x5C0 ... 0x5FF: Device 4 buffer * 0x600 ... 0x69F: Device 5 - * 0x6A0 ... 0x6BF: Device 5 buffer + * 0x6C0 ... 0x6FF: Device 5 buffer * 0x700 ... 0x79F: Device 6 - * 0x7A0 ... 0x7BF: Device 6 buffer + * 0x7C0 ... 0x7FF: Device 6 buffer * 0x800 ... 0x89F: Device 7 - * 0x8A0 ... 0x8BF: Device 7 buffer + * 0x8C0 ... 0x8FF: Device 7 buffer * 0x900 ... 0x99F: Device 8 - * 0x9A0 ... 0x9BF: Device 8 buffer + * 0x9C0 ... 0x9FF: Device 8 buffer * 0xA00 ... 0xA9F: Device 9 - * 0xAA0 ... 0xABF: Device 9 buffer + * 0xAC0 ... 0xAFF: Device 9 buffer * 0xB00 ... 0xB9F: Device 10 - * 0xBA0 ... 0xBBF: Device 10 buffer + * 0xBC0 ... 0xBFF: Device 10 buffer * 0xC00 ... 0xC9F: Device 11 - * 0xCA0 ... 0xCBF: Device 11 buffer + * 0xCC0 ... 0xCFF: Device 11 buffer * 0xD00 ... 0xD9F: Device 12 - * 0xDA0 ... 0xDBF: Device 12 buffer + * 0xDC0 ... 0xDFF: Device 12 buffer * 0xE00 ... 0xE9F: Device 13 - * 0xEA0 ... 0xEBF: Device 13 buffer + * 0xEC0 ... 0xEFF: Device 13 buffer * 0xF00 ... 0xF9F: Device 14 - * 0xFA0 ... 0xFBF: Device 14 buffer + * 0xFC0 ... 0xFFF: Device 14 buffer * 0x1000 ... 0x109F: Device 15 - * 0x10A0 ... 0x10BF: Device 15 buffer + * 0x10C0 ... 0x10BF: Device 15 buffer */ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) { @@ -XXX,XX +XXX,XX @@ static void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) aic->reg_gap_size = 0x60; aic->gap = -1; /* no gap */ aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq; - aic->pool_size = 0x20; - aic->pool_gap_size = 0xe0; - aic->pool_base = 0x1a0; + aic->pool_size = 0x40; + aic->pool_gap_size = 0xc0; + aic->pool_base = 0x1c0; aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; aic->has_dma = true; aic->mem_size = 0x2000; -- 2.43.0
Instead of introducing a dedicated TYPE_ASPEED_1040_ADC model, initialize the existing AST2700 ADC device directly for AST1040. This avoids unnecessary duplication and keeps the codebase simpler and easier to maintain. Add ADC device initialization and realization support to the AST1040 SoC model using TYPE_ASPEED_2700_ADC. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM); } + object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); + object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) aspeed_soc_ast1040_get_irq(s, uart)); } + /* ADC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0, + sc->memmap[ASPEED_DEV_ADC]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_ADC)); + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
Introduce PECI support for the AST1040 SoC model. This change adds the PECI MMIO region and IRQ mapping, initializes the PECI device instance, and realizes the controller during SoC initialization. The PECI controller is mapped at 0x74C1F000 and connected to IRQ 164. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast1040_memmap[] = { [ASPEED_DEV_SGPIOM0] = 0x74C0C000, [ASPEED_DEV_SGPIOM1] = 0x74C0D000, [ASPEED_DEV_I2C] = 0x74C0F000, + [ASPEED_DEV_PECI] = 0x74C1F000, [ASPEED_DEV_I3C] = 0x74C20000, [ASPEED_DEV_UART0] = 0x74C33000, [ASPEED_DEV_UART1] = 0x74C33100, @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast1040_irqmap[] = { [ASPEED_DEV_UART11] = 146, [ASPEED_DEV_UART12] = 147, [ASPEED_DEV_JTAG0] = 162, + [ASPEED_DEV_PECI] = 164, }; static qemu_irq aspeed_soc_ast1040_get_irq(AspeedSoCState *s, int dev) @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) } object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); + object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_ADC)); + /* PECI */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->peci), 0, + sc->memmap[ASPEED_DEV_PECI]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_PECI)); + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
The AST1040 GPIO controller is compatible with the AST2700 GPIO controller implementation. Reuse the existing "aspeed.gpio-ast2700" device model for AST1040 instead of introducing a separate implementation. Add the GPIO device initialization, MMIO mapping, and IRQ wiring for the AST1040 SoC model. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); + object_initialize_child(obj, "gpio", &s->gpio, "aspeed.gpio-ast2700"); object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0, aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_PECI)); + /* GPIO */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0, + sc->memmap[ASPEED_DEV_GPIO]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_GPIO)); + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
The AST1040 SGPIO controller is compatible with the AST2700 SGPIO controller implementation. AST1040 contains two SGPIO controllers, so reuse the existing "aspeed.sgpio-ast2700" device model instead of keeping them as unimplemented devices. MMIO mapping: - SGPIOM0 : 0x74C0C000 - SGPIOM1 : 0x74C0D000 IRQ mapping: - SGPIOM0 : IRQ 85 - SGPIOM1 : IRQ 88 Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast1040_irqmap[] = { [ASPEED_DEV_ADC] = 80, [ASPEED_DEV_GPIO] = 82, [ASPEED_DEV_SGPIOM0] = 85, + [ASPEED_DEV_SGPIOM1] = 88, [ASPEED_DEV_TIMER1] = 92, [ASPEED_DEV_I3C] = 96, /* 96 ~ 103 */ [ASPEED_DEV_WDT] = 112, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC); object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); object_initialize_child(obj, "gpio", &s->gpio, "aspeed.gpio-ast2700"); + for (i = 0; i < sc->sgpio_num; i++) { + object_initialize_child(obj, "sgpio[*]", &s->sgpiom[i], + "aspeed.sgpio-ast2700"); + } object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE); - object_initialize_child(obj, "sgpiom[0]", &s->sgpiom[0], - TYPE_UNIMPLEMENTED_DEVICE); - object_initialize_child(obj, "sgpiom[1]", &s->sgpiom[1], - TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "jtag[0]", &s->jtag[0], TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "jtag[1]", &s->jtag[1], @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_GPIO)); + /* SGPIO */ + for (i = 0; i < sc->sgpio_num; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sgpiom[i]), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sgpiom[i]), 0, + sc->memmap[ASPEED_DEV_SGPIOM0 + i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sgpiom[i]), 0, + aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_SGPIOM0 + i)); + } + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) "aspeed.udc", sc->memmap[ASPEED_DEV_UDC], 0x4000); - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->sgpiom[0]), - "aspeed.sgpiom0", - sc->memmap[ASPEED_DEV_SGPIOM0], 0x1000); - - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->sgpiom[1]), - "aspeed.sgpiom1", - sc->memmap[ASPEED_DEV_SGPIOM1], 0x1000); - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->jtag[0]), "aspeed.jtag0", sc->memmap[ASPEED_DEV_JTAG0], 0x100); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_class_init(ObjectClass *klass, const void *data) sc->sram_size[0] = 128 * KiB; sc->sram_size[1] = 16 * MiB; /* Hyper RAM */ sc->uarts_num = 13; + sc->sgpio_num = 2; sc->uarts_base = ASPEED_DEV_UART0; sc->irqmap = aspeed_soc_ast1040_irqmap; sc->memmap = aspeed_soc_ast1040_memmap; -- 2.43.0
Introduce the AST1040 I2C controller model. The AST1040 I2C controller is compatible with the AST2700 I2C controller, including DMA support and the 64-bit DMA address registers. Set has_dma64 so firmware can access the high address register and program it to zero, as the CM4 CPU only supports 32-bit addressing. AST1040 has 14 I2C buses and its HyperRAM is limited to 16 MiB, so restrict the DMA low address mask to 0x00ffffff. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- include/hw/i2c/aspeed_i2c.h | 1 + hw/i2c/aspeed_i2c.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ #define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500" #define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600" #define TYPE_ASPEED_1030_I2C TYPE_ASPEED_I2C "-ast1030" +#define TYPE_ASPEED_1040_I2C TYPE_ASPEED_I2C "-ast1040" #define TYPE_ASPEED_2700_I2C TYPE_ASPEED_I2C "-ast2700" OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static void aspeed_1030_i2c_class_init(ObjectClass *klass, const void *data) aic->dma_addr_lo_mask = 0x7fffffff; } +static void aspeed_1040_i2c_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass); + + dc->desc = "ASPEED 1040 I2C Controller"; + + /* + * AST1040 reuses the AST2700 I2C controller implementation since + * the AST1040 is compatible with AST2700. AST1040 has 14 I2C buses, + * and its HyperRAM is limited to 16 MiB, so the DMA low address + * mask is restricted accordingly. + */ + aic->num_busses = 14; + aic->reg_size = 0xa0; + aic->reg_gap_size = 0x60; + aic->gap = -1; /* no gap */ + aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq; + aic->pool_size = 0x40; + aic->pool_gap_size = 0xc0; + aic->pool_base = 0x1c0; + aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; + aic->has_dma = true; + aic->mem_size = 0x2000; + aic->has_dma64 = true; + aic->dma_addr_lo_mask = 0x00ffffff; +} + static void aspeed_2700_i2c_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_i2c_types[] = { .parent = TYPE_ASPEED_I2C, .class_init = aspeed_1030_i2c_class_init, }, + { + .name = TYPE_ASPEED_1040_I2C, + .parent = TYPE_ASPEED_I2C, + .class_init = aspeed_1040_i2c_class_init, + }, { .name = TYPE_ASPEED_2400_I2C, .parent = TYPE_ASPEED_I2C, -- 2.43.0
Introduce I2C controller support for the AST1040 SoC model. The I2C model type is selected from the SoC type name, allowing the AST1040 SoC to use the corresponding aspeed.i2c-ast1040 model. The I2C controller is mapped at 0x74C0F000 and uses IRQs 64 - 77, with one IRQ assigned per I2C bus. The controller DRAM link is connected to SRAM1 (HyperRAM) for DMA support. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- hw/arm/aspeed_ast1040.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) object_initialize_child(obj, "sgpio[*]", &s->sgpiom[i], "aspeed.sgpio-ast2700"); } + object_initialize_child(obj, "i2c", &s->i2c, TYPE_ASPEED_1040_I2C); object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_SGPIOM0 + i)); } + /* I2C */ + object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(&s->sram[1]), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0, + sc->memmap[ASPEED_DEV_I2C]); + for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) { + qemu_irq irq = qdev_get_gpio_in(DEVICE(&a->armv7m), + sc->irqmap[ASPEED_DEV_I2C] + i); + /* The AST1040 I2C controller has one IRQ per bus. */ + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq); + } + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", -- 2.43.0
Introduce onboard I2C device initialization for the AST1040 EVB model. Instantiate: - A 24C08-compatible EEPROM at address 0x50 on I2C bus 0 - A TMP105 temperature sensor at address 0x4d on I2C bus 1 Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- hw/arm/aspeed_ast1040_evb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hw/arm/aspeed_ast1040_evb.c b/hw/arm/aspeed_ast1040_evb.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040_evb.c +++ b/hw/arm/aspeed_ast1040_evb.c @@ -XXX,XX +XXX,XX @@ #include "hw/arm/aspeed_soc.h" #include "hw/core/qdev-clock.h" #include "system/system.h" +#include "hw/i2c/smbus_eeprom.h" #define AST1040_INTERNAL_FLASH_SIZE (4 * MiB) /* Main SYSCLK frequency in Hz (400MHz) */ @@ -XXX,XX +XXX,XX @@ static void aspeed_bic_machine_init(MachineState *machine) aspeed_connect_serial_hds_to_uarts(bmc); qdev_realize(DEVICE(bmc->soc), NULL, &error_abort); + if (amc->i2c_init) { + amc->i2c_init(bmc); + } + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0, AST1040_INTERNAL_FLASH_SIZE); } +static void ast1040_evb_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = bmc->soc; + uint8_t *eeprom_buf = g_malloc0(256); + + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50, eeprom_buf); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4d); +} + static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, const void *data) { @@ -XXX,XX +XXX,XX @@ static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, amc->hw_strap1 = 0; amc->hw_strap2 = 0; mc->init = aspeed_bic_machine_init; + amc->i2c_init = ast1040_evb_i2c_init; mc->default_ram_size = 0; amc->macs_mask = 0; amc->uart_default = ASPEED_DEV_UART12; -- 2.43.0
Instantiate and realize the watchdog models for the AST1040 SoC. The AST1040 watchdog controller is compatible with the AST2700 watchdog controller, so reuse the existing AST2700 watchdog model. Configure the AST1040 SoC with 8 watchdog instances and map them to their corresponding MMIO regions. The first watchdog controller (WDT0) is located at 0x74c37000, with subsequent watchdogs placed according to the controller register space size. Each watchdog is linked to the SCU device before realization to provide the required reset and system control interactions. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast1040.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_init(Object *obj) } object_initialize_child(obj, "i2c", &s->i2c, TYPE_ASPEED_1040_I2C); + for (i = 0; i < sc->wdts_num; i++) { + object_initialize_child(obj, "wdt[*]", &s->wdt[i], + "aspeed.wdt-ast2700"); + } + object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq); } + /* Watch dog */ + for (i = 0; i < sc->wdts_num; i++) { + AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]); + hwaddr wdt_offset = sc->memmap[ASPEED_DEV_WDT] + i * awc->iosize; + + object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset); + } + /* Unimplemented peripherals */ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm", @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast1040_class_init(ObjectClass *klass, const void *data) sc->sram_size[1] = 16 * MiB; /* Hyper RAM */ sc->uarts_num = 13; sc->sgpio_num = 2; + sc->wdts_num = 8; sc->uarts_base = ASPEED_DEV_UART0; sc->irqmap = aspeed_soc_ast1040_irqmap; sc->memmap = aspeed_soc_ast1040_memmap; -- 2.43.0