aspeed queue:

* I2C support for AST2700
 * Coverity fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmbofzEACgkQUaNDx8/7
 7KHo4g//RtzY1oM+5xbX7LA4Nb45EJtAs9+UvbvDF7++NF9Nd4VThdoyBSvzyqd8
 9Z35Mfoh1xce7+Qz/QtobbRkPLKtq7rfmj4lCkXZRGR/0nbDteqyLOqDM/E/GSBc
 mEaMG9sT2L1t9SrKOYIhgoPSpS0kpJ0YHfMLt5DcTjLQ1g8OB7ByzOPoPSBzTPAf
 QLL/v0GTxdqQPRhcZJKGclkjeVwBtFpo1rbDe/tHfFKC51g3cROGyQEswuPxRqDB
 Y3CQ0WC7awqSg7WAUwTfyb6LNSmYoiycGKv/gi06kc/mxjpf2qQ2khX4diiPoOj0
 Ak1b/dv2DWKE8LDYw7ew44UdPyIhGhgFeYeJ1olz5oLUcdcd4PuBWBvLUgpJKEfk
 HRXcJyhat3rwWGYzrdCJbBPN6CPncWjyifg1X6jK6Eu4wnfdpB9m64xFg8TpALaz
 SRZGg0ahldBwU6jjDO3x/RMWzKCtzwAjDuLfxSlqDGPx5OL+0dDDEa+xj45VzzBZ
 aT5Kcy9ga9DgRUw4wds3NHz9uCxwXoktDkW3vKMeMdftAf6er+Inhe8FHer/JSh4
 wuCxUDYIUSate5QoVucHAAM3DqOCQ1ascugufluXAR4StJ/u2b3SXU881C7v4crP
 NDncQEsWgya+Ykv9lXgulDxZrc8qsSmj4aoRNtJHaGsxmb4RwSY=
 =NyK5
 -----END PGP SIGNATURE-----

Merge tag 'pull-aspeed-20240916' of https://github.com/legoater/qemu into staging

aspeed queue:

* I2C support for AST2700
* Coverity fixes

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmbofzEACgkQUaNDx8/7
# 7KHo4g//RtzY1oM+5xbX7LA4Nb45EJtAs9+UvbvDF7++NF9Nd4VThdoyBSvzyqd8
# 9Z35Mfoh1xce7+Qz/QtobbRkPLKtq7rfmj4lCkXZRGR/0nbDteqyLOqDM/E/GSBc
# mEaMG9sT2L1t9SrKOYIhgoPSpS0kpJ0YHfMLt5DcTjLQ1g8OB7ByzOPoPSBzTPAf
# QLL/v0GTxdqQPRhcZJKGclkjeVwBtFpo1rbDe/tHfFKC51g3cROGyQEswuPxRqDB
# Y3CQ0WC7awqSg7WAUwTfyb6LNSmYoiycGKv/gi06kc/mxjpf2qQ2khX4diiPoOj0
# Ak1b/dv2DWKE8LDYw7ew44UdPyIhGhgFeYeJ1olz5oLUcdcd4PuBWBvLUgpJKEfk
# HRXcJyhat3rwWGYzrdCJbBPN6CPncWjyifg1X6jK6Eu4wnfdpB9m64xFg8TpALaz
# SRZGg0ahldBwU6jjDO3x/RMWzKCtzwAjDuLfxSlqDGPx5OL+0dDDEa+xj45VzzBZ
# aT5Kcy9ga9DgRUw4wds3NHz9uCxwXoktDkW3vKMeMdftAf6er+Inhe8FHer/JSh4
# wuCxUDYIUSate5QoVucHAAM3DqOCQ1ascugufluXAR4StJ/u2b3SXU881C7v4crP
# NDncQEsWgya+Ykv9lXgulDxZrc8qsSmj4aoRNtJHaGsxmb4RwSY=
# =NyK5
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 16 Sep 2024 19:55:45 BST
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* tag 'pull-aspeed-20240916' of https://github.com/legoater/qemu:
  machine_aspeed.py: Update to test I2C for AST2700
  aspeed: Add tmp105 in i2c bus 0 for AST2700
  aspeed/soc: Support I2C for AST2700
  aspeed/soc: Introduce a new API to get the device irq
  hw/i2c/aspeed: Add support for 64 bit addresses
  hw/i2c/aspeed: Add support for Tx/Rx buffer 64 bit addresses
  hw/i2c/aspeed: Add AST2700 support
  hw/i2c/aspeed: Introduce a new dma_dram_offset attribute in AspeedI2Cbus
  hw/i2c/aspeed: Support discontinuous poll buffer memory region of I2C bus
  hw/i2c/aspeed: Introduce a new bus pool buffer attribute in AspeedI2Cbus
  hw/i2c/aspeed: Support discontinuous register memory region of I2C bus
  hw/gpio/aspeed_gpio: Avoid shift into sign bit

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2024-09-17 11:39:58 +01:00
commit 6fe7fc96e7
6 changed files with 363 additions and 48 deletions

View File

@ -1650,6 +1650,15 @@ static void aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
}
#ifdef TARGET_AARCH64
static void ast2700_evb_i2c_init(AspeedMachineState *bmc)
{
AspeedSoCState *soc = bmc->soc;
/* LM75 is compatible with TMP105 driver */
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0),
TYPE_TMP105, 0x4d);
}
static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@ -1664,6 +1673,7 @@ static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON;
amc->uart_default = ASPEED_DEV_UART12;
amc->i2c_init = ast2700_evb_i2c_init;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
}

View File

@ -61,6 +61,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
[ASPEED_GIC_DIST] = 0x12200000,
[ASPEED_GIC_REDIST] = 0x12280000,
[ASPEED_DEV_ADC] = 0x14C00000,
[ASPEED_DEV_I2C] = 0x14C0F000,
};
#define AST2700_MAX_IRQ 288
@ -193,6 +194,27 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
return qdev_get_gpio_in(DEVICE(&a->gic), sc->irqmap[dev]);
}
static qemu_irq aspeed_soc_ast2700_get_irq_index(AspeedSoCState *s, int dev,
int index)
{
Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
int i;
for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
aspeed_soc_ast2700_gic_intcmap[i].ptr[dev] + index);
}
}
/*
* Invalid orgate index, device irq should be 128 to 136.
*/
g_assert_not_reached();
}
static uint64_t aspeed_ram_capacity_read(void *opaque, hwaddr addr,
unsigned int size)
{
@ -348,6 +370,9 @@ static void aspeed_soc_ast2700_init(Object *obj)
snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
object_initialize_child(obj, "adc", &s->adc, typename);
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
object_initialize_child(obj, "i2c", &s->i2c, typename);
}
/*
@ -431,6 +456,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
AspeedINTCClass *ic = ASPEED_INTC_GET_CLASS(&a->intc);
g_autofree char *sram_name = NULL;
qemu_irq irq;
/* Default boot region (SPI memory or ROMs) */
memory_region_init(&s->spi_boot_container, OBJECT(s),
@ -613,6 +639,25 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* I2C */
object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),
&error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
return;
}
aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
/*
* The AST2700 I2C controller has one source INTC per bus.
* I2C buses interrupt are connected to GICINT130_INTC
* from bit 0 to bit 15.
* I2C bus 0 is connected to GICINT130_INTC at bit 0.
* I2C bus 15 is connected to GICINT130_INTC at bit 15.
*/
irq = aspeed_soc_ast2700_get_irq_index(s, ASPEED_DEV_I2C, i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq);
}
create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000);
create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000);
create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000);

View File

@ -281,7 +281,7 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
diff &= mode_mask;
if (diff) {
for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) {
uint32_t mask = 1 << gpio;
uint32_t mask = 1U << gpio;
/* If the gpio needs to be updated... */
if (!(diff & mask)) {

View File

@ -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) {
@ -137,6 +140,7 @@ static uint64_t aspeed_i2c_bus_old_read(AspeedI2CBus *bus, hwaddr offset,
static uint64_t aspeed_i2c_bus_new_read(AspeedI2CBus *bus, hwaddr offset,
unsigned size)
{
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
uint64_t value = bus->regs[offset / sizeof(*bus->regs)];
switch (offset) {
@ -150,9 +154,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,11 +163,24 @@ 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:
value = SHARED_FIELD_DP32(value, BUS_BUSY_STS, i2c_bus_busy(bus->bus));
break;
case A_I2CM_DMA_TX_ADDR_HI:
case A_I2CM_DMA_RX_ADDR_HI:
case A_I2CS_DMA_TX_ADDR_HI:
case A_I2CS_DMA_RX_ADDR_HI:
if (!aic->has_dma64) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA 64 bits support\n",
__func__);
value = -1;
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
@ -210,18 +225,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 +306,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 +337,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 +653,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;
@ -721,6 +742,56 @@ 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",
__func__);
break;
}
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) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA 64 bits support\n",
__func__);
break;
}
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,
"%s: Slave mode DMA TX Addr high is not implemented\n",
__func__);
break;
case A_I2CS_DMA_RX_ADDR_HI:
if (!aic->has_dma64) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA 64 bits support\n",
__func__);
break;
}
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",
__func__, offset);
@ -811,7 +882,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:
@ -941,12 +1013,49 @@ static const MemoryRegionOps aspeed_i2c_share_pool_ops = {
},
};
static uint64_t aspeed_i2c_bus_pool_read(void *opaque, hwaddr offset,
unsigned size)
{
AspeedI2CBus *s = opaque;
uint64_t ret = 0;
int i;
for (i = 0; i < size; i++) {
ret |= (uint64_t) s->pool[offset + i] << (8 * i);
}
return ret;
}
static void aspeed_i2c_bus_pool_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
AspeedI2CBus *s = opaque;
int i;
for (i = 0; i < size; i++) {
s->pool[offset + i] = (value >> (8 * i)) & 0xFF;
}
}
static const MemoryRegionOps aspeed_i2c_bus_pool_ops = {
.read = aspeed_i2c_bus_pool_read,
.write = aspeed_i2c_bus_pool_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 4,
},
};
static const VMStateDescription aspeed_i2c_bus_vmstate = {
.name = TYPE_ASPEED_I2C,
.version_id = 5,
.minimum_version_id = 5,
.version_id = 6,
.minimum_version_id = 6,
.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()
}
};
@ -996,7 +1105,21 @@ static void aspeed_i2c_instance_init(Object *obj)
* 0x140 ... 0x17F: Device 5
* 0x180 ... 0x1BF: Device 6
* 0x1C0 ... 0x1FF: Device 7
* 0x200 ... 0x2FF: Buffer Pool (AST2500 unused in linux driver)
* 0x200 ... 0x20F: Device 1 buffer (AST2500 unused in linux driver)
* 0x210 ... 0x21F: Device 2 buffer
* 0x220 ... 0x22F: Device 3 buffer
* 0x230 ... 0x23F: Device 4 buffer
* 0x240 ... 0x24F: Device 5 buffer
* 0x250 ... 0x25F: Device 6 buffer
* 0x260 ... 0x26F: Device 7 buffer
* 0x270 ... 0x27F: Device 8 buffer
* 0x280 ... 0x28F: Device 9 buffer
* 0x290 ... 0x29F: Device 10 buffer
* 0x2A0 ... 0x2AF: Device 11 buffer
* 0x2B0 ... 0x2BF: Device 12 buffer
* 0x2C0 ... 0x2CF: Device 13 buffer
* 0x2D0 ... 0x2DF: Device 14 buffer
* 0x2E0 ... 0x2FF: Reserved
* 0x300 ... 0x33F: Device 8
* 0x340 ... 0x37F: Device 9
* 0x380 ... 0x3BF: Device 10
@ -1005,6 +1128,76 @@ static void aspeed_i2c_instance_init(Object *obj)
* 0x440 ... 0x47F: Device 13
* 0x480 ... 0x4BF: Device 14
* 0x800 ... 0xFFF: Buffer Pool (AST2400 unused in linux driver)
*
* Address Definitions (AST2600 and AST1030)
* 0x000 ... 0x07F: Global Register
* 0x080 ... 0x0FF: Device 1
* 0x100 ... 0x17F: Device 2
* 0x180 ... 0x1FF: Device 3
* 0x200 ... 0x27F: Device 4
* 0x280 ... 0x2FF: Device 5
* 0x300 ... 0x37F: Device 6
* 0x380 ... 0x3FF: Device 7
* 0x400 ... 0x47F: Device 8
* 0x480 ... 0x4FF: Device 9
* 0x500 ... 0x57F: Device 10
* 0x580 ... 0x5FF: Device 11
* 0x600 ... 0x67F: Device 12
* 0x680 ... 0x6FF: Device 13
* 0x700 ... 0x77F: Device 14
* 0x780 ... 0x7FF: Device 15 (15 and 16 unused in AST1030)
* 0x800 ... 0x87F: Device 16
* 0xC00 ... 0xC1F: Device 1 buffer
* 0xC20 ... 0xC3F: Device 2 buffer
* 0xC40 ... 0xC5F: Device 3 buffer
* 0xC60 ... 0xC7F: Device 4 buffer
* 0xC80 ... 0xC9F: Device 5 buffer
* 0xCA0 ... 0xCBF: Device 6 buffer
* 0xCC0 ... 0xCDF: Device 7 buffer
* 0xCE0 ... 0xCFF: Device 8 buffer
* 0xD00 ... 0xD1F: Device 9 buffer
* 0xD20 ... 0xD3F: Device 10 buffer
* 0xD40 ... 0xD5F: Device 11 buffer
* 0xD60 ... 0xD7F: Device 12 buffer
* 0xD80 ... 0xD9F: Device 13 buffer
* 0xDA0 ... 0xDBF: Device 14 buffer
* 0xDC0 ... 0xDDF: Device 15 buffer (15 and 16 unused in AST1030)
* 0xDE0 ... 0xDFF: Device 16 buffer
*
* Address Definitions (AST2700)
* 0x000 ... 0x0FF: Global Register
* 0x100 ... 0x17F: Device 0
* 0x1A0 ... 0x1BF: Device 0 buffer
* 0x200 ... 0x27F: Device 1
* 0x2A0 ... 0x2BF: Device 1 buffer
* 0x300 ... 0x37F: Device 2
* 0x3A0 ... 0x3BF: Device 2 buffer
* 0x400 ... 0x47F: Device 3
* 0x4A0 ... 0x4BF: Device 3 buffer
* 0x500 ... 0x57F: Device 4
* 0x5A0 ... 0x5BF: Device 4 buffer
* 0x600 ... 0x67F: Device 5
* 0x6A0 ... 0x6BF: Device 5 buffer
* 0x700 ... 0x77F: Device 6
* 0x7A0 ... 0x7BF: Device 6 buffer
* 0x800 ... 0x87F: Device 7
* 0x8A0 ... 0x8BF: Device 7 buffer
* 0x900 ... 0x97F: Device 8
* 0x9A0 ... 0x9BF: Device 8 buffer
* 0xA00 ... 0xA7F: Device 9
* 0xAA0 ... 0xABF: Device 9 buffer
* 0xB00 ... 0xB7F: Device 10
* 0xBA0 ... 0xBBF: Device 10 buffer
* 0xC00 ... 0xC7F: Device 11
* 0xCA0 ... 0xCBF: Device 11 buffer
* 0xD00 ... 0xD7F: Device 12
* 0xDA0 ... 0xDBF: Device 12 buffer
* 0xE00 ... 0xE7F: Device 13
* 0xEA0 ... 0xEBF: Device 13 buffer
* 0xF00 ... 0xF7F: Device 14
* 0xFA0 ... 0xFBF: Device 14 buffer
* 0x1000 ... 0x107F: Device 15
* 0x10A0 ... 0x10BF: Device 15 buffer
*/
static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
{
@ -1012,6 +1205,8 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
AspeedI2CState *s = ASPEED_I2C(dev);
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
uint32_t reg_offset = aic->reg_size + aic->reg_gap_size;
uint32_t pool_offset = aic->pool_size + aic->pool_gap_size;
sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i2c_ctrl_ops, s,
@ -1034,14 +1229,23 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
return;
}
memory_region_add_subregion(&s->iomem, aic->reg_size * (i + offset),
memory_region_add_subregion(&s->iomem, reg_offset * (i + offset),
&s->busses[i].mr);
}
memory_region_init_io(&s->pool_iomem, OBJECT(s),
&aspeed_i2c_share_pool_ops, s,
"aspeed.i2c-share-pool", aic->pool_size);
memory_region_add_subregion(&s->iomem, aic->pool_base, &s->pool_iomem);
if (aic->has_share_pool) {
memory_region_init_io(&s->pool_iomem, OBJECT(s),
&aspeed_i2c_share_pool_ops, s,
"aspeed.i2c-share-pool", aic->pool_size);
memory_region_add_subregion(&s->iomem, aic->pool_base,
&s->pool_iomem);
} else {
for (i = 0; i < aic->num_busses; i++) {
memory_region_add_subregion(&s->iomem,
aic->pool_base + (pool_offset * i),
&s->busses[i].mr_pool);
}
}
if (aic->has_dma) {
if (!s->dram_mr) {
@ -1092,8 +1296,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);
@ -1159,10 +1364,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);
@ -1217,6 +1422,7 @@ static void aspeed_i2c_bus_realize(DeviceState *dev, Error **errp)
AspeedI2CBus *s = ASPEED_I2C_BUS(dev);
AspeedI2CClass *aic;
g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I2C_BUS ".%d", s->id);
g_autofree char *pool_name = g_strdup_printf("%s.pool", name);
if (!s->controller) {
error_setg(errp, TYPE_ASPEED_I2C_BUS ": 'controller' link not set");
@ -1234,6 +1440,10 @@ static void aspeed_i2c_bus_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i2c_bus_ops,
s, name, aic->reg_size);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
memory_region_init_io(&s->mr_pool, OBJECT(s), &aspeed_i2c_bus_pool_ops,
s, pool_name, aic->pool_size);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr_pool);
}
static Property aspeed_i2c_bus_properties[] = {
@ -1286,6 +1496,7 @@ static void aspeed_2400_i2c_class_init(ObjectClass *klass, void *data)
aic->reg_size = 0x40;
aic->gap = 7;
aic->bus_get_irq = aspeed_2400_i2c_bus_get_irq;
aic->has_share_pool = true;
aic->pool_size = 0x800;
aic->pool_base = 0x800;
aic->bus_pool_base = aspeed_2400_i2c_bus_pool_base;
@ -1305,7 +1516,7 @@ static qemu_irq aspeed_2500_i2c_bus_get_irq(AspeedI2CBus *bus)
static uint8_t *aspeed_2500_i2c_bus_pool_base(AspeedI2CBus *bus)
{
return &bus->controller->share_pool[bus->id * 0x10];
return bus->pool;
}
static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
@ -1319,7 +1530,7 @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
aic->reg_size = 0x40;
aic->gap = 7;
aic->bus_get_irq = aspeed_2500_i2c_bus_get_irq;
aic->pool_size = 0x100;
aic->pool_size = 0x10;
aic->pool_base = 0x200;
aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
aic->check_sram = true;
@ -1338,11 +1549,6 @@ static qemu_irq aspeed_2600_i2c_bus_get_irq(AspeedI2CBus *bus)
return bus->irq;
}
static uint8_t *aspeed_2600_i2c_bus_pool_base(AspeedI2CBus *bus)
{
return &bus->controller->share_pool[bus->id * 0x20];
}
static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -1354,9 +1560,9 @@ static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)
aic->reg_size = 0x80;
aic->gap = -1; /* no gap */
aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq;
aic->pool_size = 0x200;
aic->pool_size = 0x20;
aic->pool_base = 0xC00;
aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;
aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
aic->has_dma = true;
aic->mem_size = 0x1000;
}
@ -1378,9 +1584,9 @@ static void aspeed_1030_i2c_class_init(ObjectClass *klass, void *data)
aic->reg_size = 0x80;
aic->gap = -1; /* no gap */
aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq;
aic->pool_size = 0x200;
aic->pool_size = 0x20;
aic->pool_base = 0xC00;
aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;
aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
aic->has_dma = true;
aic->mem_size = 0x10000;
}
@ -1391,6 +1597,33 @@ static const TypeInfo aspeed_1030_i2c_info = {
.class_init = aspeed_1030_i2c_class_init,
};
static void aspeed_2700_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass);
dc->desc = "ASPEED 2700 I2C Controller";
aic->num_busses = 16;
aic->reg_size = 0x80;
aic->reg_gap_size = 0x80;
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->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
aic->has_dma = true;
aic->mem_size = 0x2000;
aic->has_dma64 = true;
}
static const TypeInfo aspeed_2700_i2c_info = {
.name = TYPE_ASPEED_2700_I2C,
.parent = TYPE_ASPEED_I2C,
.class_init = aspeed_2700_i2c_class_init,
};
static void aspeed_i2c_register_types(void)
{
type_register_static(&aspeed_i2c_bus_info);
@ -1400,6 +1633,7 @@ static void aspeed_i2c_register_types(void)
type_register_static(&aspeed_2500_i2c_info);
type_register_static(&aspeed_2600_i2c_info);
type_register_static(&aspeed_1030_i2c_info);
type_register_static(&aspeed_2700_i2c_info);
}
type_init(aspeed_i2c_register_types)

View File

@ -31,12 +31,14 @@
#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_2700_I2C TYPE_ASPEED_I2C "-ast2700"
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_OLD_NUM_REG 11
#define ASPEED_I2C_NEW_NUM_REG 22
#define ASPEED_I2C_NEW_NUM_REG 28
#define A_I2CD_M_STOP_CMD BIT(5)
#define A_I2CD_M_RX_CMD BIT(3)
@ -225,6 +227,15 @@ REG32(I2CS_DMA_LEN_STS, 0x4c)
FIELD(I2CS_DMA_LEN_STS, TX_LEN, 0, 13)
REG32(I2CC_DMA_ADDR, 0x50)
REG32(I2CC_DMA_LEN, 0x54)
/* DMA 64bits */
REG32(I2CM_DMA_TX_ADDR_HI, 0x60)
FIELD(I2CM_DMA_TX_ADDR_HI, ADDR_HI, 0, 7)
REG32(I2CM_DMA_RX_ADDR_HI, 0x64)
FIELD(I2CM_DMA_RX_ADDR_HI, ADDR_HI, 0, 7)
REG32(I2CS_DMA_TX_ADDR_HI, 0x68)
FIELD(I2CS_DMA_TX_ADDR_HI, ADDR_HI, 0, 7)
REG32(I2CS_DMA_RX_ADDR_HI, 0x6c)
FIELD(I2CS_DMA_RX_ADDR_HI, ADDR_HI, 0, 7)
struct AspeedI2CState;
@ -239,12 +250,15 @@ struct AspeedI2CBus {
I2CSlave *slave;
MemoryRegion mr;
MemoryRegion mr_pool;
I2CBus *bus;
uint8_t id;
qemu_irq irq;
uint32_t regs[ASPEED_I2C_NEW_NUM_REG];
uint8_t pool[ASPEED_I2C_BUS_POOL_SIZE];
uint64_t dma_dram_offset;
};
struct AspeedI2CState {
@ -275,15 +289,19 @@ struct AspeedI2CClass {
uint8_t num_busses;
uint8_t reg_size;
uint32_t reg_gap_size;
uint8_t gap;
qemu_irq (*bus_get_irq)(AspeedI2CBus *);
uint64_t pool_size;
hwaddr pool_base;
uint32_t pool_gap_size;
uint8_t *(*bus_pool_base)(AspeedI2CBus *);
bool check_sram;
bool has_dma;
bool has_share_pool;
uint64_t mem_size;
bool has_dma64;
};
static inline bool aspeed_i2c_is_new_mode(AspeedI2CState *s)
@ -363,14 +381,6 @@ static inline uint32_t aspeed_i2c_bus_dma_len_offset(AspeedI2CBus *bus)
return R_I2CD_DMA_LEN;
}
static inline uint32_t aspeed_i2c_bus_dma_addr_offset(AspeedI2CBus *bus)
{
if (aspeed_i2c_is_new_mode(bus->controller)) {
return R_I2CC_DMA_ADDR;
}
return R_I2CD_DMA_ADDR;
}
static inline bool aspeed_i2c_bus_is_master(AspeedI2CBus *bus)
{
return SHARED_ARRAY_FIELD_EX32(bus->regs, aspeed_i2c_bus_ctrl_offset(bus),

View File

@ -433,9 +433,25 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
f'loader,addr=0x430000000,cpu-num={i}')
self.vm.add_args('-smp', str(num_cpu))
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')
self.wait_for_console_pattern('nodistro.0 ast2700-default ttyS12')
self.ssh_connect('root', '0penBmc', False)
self.ssh_command('dmesg -c > /dev/null')
self.ssh_command_output_contains(
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device '
'&& dmesg -c',
'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d');
self.ssh_command_output_contains(
'cat /sys/class/hwmon/hwmon20/temp1_input', '0')
self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000)
self.ssh_command_output_contains(
'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')
class AST2x00MachineMMC(QemuSystemTest):