diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-09-21 13:58:09 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-09-21 13:58:09 +0100 |
commit | 1c81a38c5ae0c4275b5472f690b76c194a03dee8 (patch) | |
tree | 80d84df788d0705f2c0f69a1639cf0993175fe02 /hw | |
parent | 326ff8dd09556fc2e257196c49f35009700794ac (diff) | |
parent | febbe308bf9477767ca92e8ed5f265b0001fcef9 (diff) | |
download | qemu-1c81a38c5ae0c4275b5472f690b76c194a03dee8.zip qemu-1c81a38c5ae0c4275b5472f690b76c194a03dee8.tar.gz qemu-1c81a38c5ae0c4275b5472f690b76c194a03dee8.tar.bz2 |
Merge remote-tracking branch 'remotes/legoater/tags/pull-aspeed-20210920' into staging
Aspeed patches :
* MAC enablement fixes (Guenter)
* Watchdog and pca9552 fixes (Andrew)
* GPIO fixes (Joel)
* AST2600A3 SoC and DPS310 models (Joel)
* New Fuji BMC machine (Peter)
# gpg: Signature made Mon 20 Sep 2021 07:51:23 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
* remotes/legoater/tags/pull-aspeed-20210920:
hw/arm/aspeed: Add Fuji machine type
hw/arm/aspeed: Allow machine to set UART default
hw/arm/aspeed: Initialize AST2600 UART clock selection registers
arm/aspeed: Add DPS310 to Witherspoon and Rainier
hw/misc: Add Infineon DPS310 sensor model
aspeed: Emulate the AST2600A3
arm/aspeed: rainier: Add i2c eeproms and muxes
misc/pca9552: Fix LED status register indexing in pca955x_get_led()
hw: aspeed_gpio: Clarify GPIO controller name
hw: aspeed_gpio: Simplify 1.8V defines
watchdog: aspeed: Fix sequential control writes
watchdog: aspeed: Sanitize control register values
hw: arm: aspeed: Enable mac0/1 instead of mac1/2 for g220a
hw: arm: aspeed: Enable eth0 interface for aspeed-ast2600-evb
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/Kconfig | 1 | ||||
-rw-r--r-- | hw/arm/aspeed.c | 182 | ||||
-rw-r--r-- | hw/arm/aspeed_ast2600.c | 14 | ||||
-rw-r--r-- | hw/arm/aspeed_soc.c | 8 | ||||
-rw-r--r-- | hw/gpio/aspeed_gpio.c | 97 | ||||
-rw-r--r-- | hw/misc/aspeed_scu.c | 40 | ||||
-rw-r--r-- | hw/misc/pca9552.c | 2 | ||||
-rw-r--r-- | hw/sensor/Kconfig | 4 | ||||
-rw-r--r-- | hw/sensor/dps310.c | 225 | ||||
-rw-r--r-- | hw/sensor/meson.build | 1 | ||||
-rw-r--r-- | hw/watchdog/wdt_aspeed.c | 26 |
11 files changed, 524 insertions, 76 deletions
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 78fdd1b..18832ab 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -428,6 +428,7 @@ config ASPEED_SOC select DS1338 select FTGMAC100 select I2C + select DPS310 select PCA9552 select SERIAL select SMBUS_EEPROM diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 9d43e26..ba5f1dc 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -159,6 +159,10 @@ struct AspeedMachineState { #define RAINIER_BMC_HW_STRAP1 0x00000000 #define RAINIER_BMC_HW_STRAP2 0x00000000 +/* Fuji hardware value */ +#define FUJI_BMC_HW_STRAP1 0x00000000 +#define FUJI_BMC_HW_STRAP2 0x00000000 + /* * The max ram region is for firmwares that scan the address space * with load/store to guess how much RAM the SoC has. @@ -350,6 +354,8 @@ static void aspeed_machine_init(MachineState *machine) object_property_set_int(OBJECT(&bmc->soc), "hw-prot-key", ASPEED_SCU_PROT_KEY, &error_abort); } + qdev_prop_set_uint32(DEVICE(&bmc->soc), "uart-default", + amc->uart_default); qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort); memory_region_add_subregion(get_system_memory(), @@ -602,7 +608,6 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) /* Bus 3: TODO bmp280@77 */ /* Bus 3: TODO max31785@52 */ - /* Bus 3: TODO dps310@76 */ dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60)); qdev_prop_set_string(dev, "description", "pca1"); i2c_slave_realize_and_unref(I2C_SLAVE(dev), @@ -617,6 +622,7 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) qdev_connect_gpio_out(dev, pca1_leds[i].gpio_id, qdev_get_gpio_in(DEVICE(led), 0)); } + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "dps310", 0x76); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); @@ -674,9 +680,21 @@ static void g220a_bmc_i2c_init(AspeedMachineState *bmc) eeprom_buf); } +static void aspeed_eeprom_init(I2CBus *bus, uint8_t addr, uint32_t rsize) +{ + I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr); + DeviceState *dev = DEVICE(i2c_dev); + + qdev_prop_set_uint32(dev, "rom-size", rsize); + i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); +} + static void rainier_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; + I2CSlave *i2c_mux; + + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 0), 0x51, 32 * KiB); /* The rainier expects a TMP275 but a TMP105 is compatible */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105, @@ -685,11 +703,20 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) 0x49); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105, 0x4a); + i2c_mux = i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), + "pca9546", 0x70); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x51, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 0x52, 64 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105, 0x48); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105, 0x49); + i2c_mux = i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), + "pca9546", 0x70); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x51, 64 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, 0x48); @@ -697,18 +724,28 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) 0x4a); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, 0x4b); + i2c_mux = i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), + "pca9546", 0x70); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x51, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 0x50, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 3), 0x51, 64 * KiB); - /* Bus 7: TODO dps310@76 */ /* Bus 7: TODO max31785@52 */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x61); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "dps310", 0x76); /* Bus 7: TODO si7021-a20@20 */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105, 0x48); + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 7), 0x50, 64 * KiB); + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 7), 0x51, 64 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105, 0x48); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105, 0x4a); + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x50, 64 * KiB); + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 64 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x61); /* Bus 8: ucd90320@11 */ /* Bus 8: ucd90320@b */ @@ -716,14 +753,112 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4d); + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 9), 0x50, 128 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4d); + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 10), 0x50, 128 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, 0x48); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, 0x49); + i2c_mux = i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), + "pca9546", 0x70); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); + aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x51, 64 * KiB); + + + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 13), 0x50, 64 * KiB); + + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 14), 0x50, 64 * KiB); + + aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 15), 0x50, 64 * KiB); +} + +static void get_pca9548_channels(I2CBus *bus, uint8_t mux_addr, + I2CBus **channels) +{ + I2CSlave *mux = i2c_slave_create_simple(bus, "pca9548", mux_addr); + for (int i = 0; i < 8; i++) { + channels[i] = pca954x_i2c_get_bus(mux, i); + } +} + +#define TYPE_LM75 TYPE_TMP105 +#define TYPE_TMP75 TYPE_TMP105 +#define TYPE_TMP422 "tmp422" + +static void fuji_bmc_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + I2CBus *i2c[144] = {}; + + for (int i = 0; i < 16; i++) { + i2c[i] = aspeed_i2c_get_bus(&soc->i2c, i); + } + I2CBus *i2c180 = i2c[2]; + I2CBus *i2c480 = i2c[8]; + I2CBus *i2c600 = i2c[11]; + + get_pca9548_channels(i2c180, 0x70, &i2c[16]); + get_pca9548_channels(i2c480, 0x70, &i2c[24]); + /* NOTE: The device tree skips [32, 40) in the alias numbering */ + get_pca9548_channels(i2c600, 0x77, &i2c[40]); + get_pca9548_channels(i2c[24], 0x71, &i2c[48]); + get_pca9548_channels(i2c[25], 0x72, &i2c[56]); + get_pca9548_channels(i2c[26], 0x76, &i2c[64]); + get_pca9548_channels(i2c[27], 0x76, &i2c[72]); + for (int i = 0; i < 8; i++) { + get_pca9548_channels(i2c[40 + i], 0x76, &i2c[80 + i * 8]); + } + + i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4c); + i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4d); + + aspeed_eeprom_init(i2c[19], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[20], 0x50, 2 * KiB); + aspeed_eeprom_init(i2c[22], 0x52, 2 * KiB); + + i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x48); + i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x49); + i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x4a); + i2c_slave_create_simple(i2c[3], TYPE_TMP422, 0x4c); + + aspeed_eeprom_init(i2c[8], 0x51, 64 * KiB); + i2c_slave_create_simple(i2c[8], TYPE_LM75, 0x4a); + + i2c_slave_create_simple(i2c[50], TYPE_LM75, 0x4c); + aspeed_eeprom_init(i2c[50], 0x52, 64 * KiB); + i2c_slave_create_simple(i2c[51], TYPE_TMP75, 0x48); + i2c_slave_create_simple(i2c[52], TYPE_TMP75, 0x49); + + i2c_slave_create_simple(i2c[59], TYPE_TMP75, 0x48); + i2c_slave_create_simple(i2c[60], TYPE_TMP75, 0x49); + + aspeed_eeprom_init(i2c[65], 0x53, 64 * KiB); + i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x49); + i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x48); + aspeed_eeprom_init(i2c[68], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[69], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[70], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[71], 0x52, 64 * KiB); + + aspeed_eeprom_init(i2c[73], 0x53, 64 * KiB); + i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x49); + i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x48); + aspeed_eeprom_init(i2c[76], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[77], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[78], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[79], 0x52, 64 * KiB); + aspeed_eeprom_init(i2c[28], 0x50, 2 * KiB); + + for (int i = 0; i < 8; i++) { + aspeed_eeprom_init(i2c[81 + i * 8], 0x56, 64 * KiB); + i2c_slave_create_simple(i2c[82 + i * 8], TYPE_TMP75, 0x48); + i2c_slave_create_simple(i2c[83 + i * 8], TYPE_TMP75, 0x4b); + i2c_slave_create_simple(i2c[84 + i * 8], TYPE_TMP75, 0x4a); + } } static bool aspeed_get_mmio_exec(Object *obj, Error **errp) @@ -804,6 +939,7 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->no_parallel = 1; mc->default_ram_id = "ram"; amc->macs_mask = ASPEED_MAC0_ON; + amc->uart_default = ASPEED_DEV_UART5; aspeed_machine_class_props_init(oc); } @@ -953,13 +1089,14 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data) AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); mc->desc = "Aspeed AST2600 EVB (Cortex-A7)"; - amc->soc_name = "ast2600-a1"; + amc->soc_name = "ast2600-a3"; amc->hw_strap1 = AST2600_EVB_HW_STRAP1; amc->hw_strap2 = AST2600_EVB_HW_STRAP2; amc->fmc_model = "w25q512jv"; amc->spi_model = "mx66u51235f"; amc->num_cs = 1; - amc->macs_mask = ASPEED_MAC1_ON | ASPEED_MAC2_ON | ASPEED_MAC3_ON; + amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON | + ASPEED_MAC3_ON; amc->i2c_init = ast2600_evb_i2c_init; mc->default_ram_size = 1 * GiB; mc->default_cpus = mc->min_cpus = mc->max_cpus = @@ -972,7 +1109,7 @@ static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data) AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); mc->desc = "OpenPOWER Tacoma BMC (Cortex-A7)"; - amc->soc_name = "ast2600-a1"; + amc->soc_name = "ast2600-a3"; amc->hw_strap1 = TACOMA_BMC_HW_STRAP1; amc->hw_strap2 = TACOMA_BMC_HW_STRAP2; amc->fmc_model = "mx66l1g45g"; @@ -996,7 +1133,7 @@ static void aspeed_machine_g220a_class_init(ObjectClass *oc, void *data) amc->fmc_model = "n25q512a"; amc->spi_model = "mx25l25635e"; amc->num_cs = 2; - amc->macs_mask = ASPEED_MAC1_ON | ASPEED_MAC2_ON; + amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON; amc->i2c_init = g220a_bmc_i2c_init; mc->default_ram_size = 1024 * MiB; mc->default_cpus = mc->min_cpus = mc->max_cpus = @@ -1009,7 +1146,7 @@ static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data) AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); mc->desc = "IBM Rainier BMC (Cortex-A7)"; - amc->soc_name = "ast2600-a1"; + amc->soc_name = "ast2600-a3"; amc->hw_strap1 = RAINIER_BMC_HW_STRAP1; amc->hw_strap2 = RAINIER_BMC_HW_STRAP2; amc->fmc_model = "mx66l1g45g"; @@ -1022,6 +1159,33 @@ static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); }; +/* On 32-bit hosts, lower RAM to 1G because of the 2047 MB limit */ +#if HOST_LONG_BITS == 32 +#define FUJI_BMC_RAM_SIZE (1 * GiB) +#else +#define FUJI_BMC_RAM_SIZE (2 * GiB) +#endif + +static void aspeed_machine_fuji_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook Fuji BMC (Cortex-A7)"; + amc->soc_name = "ast2600-a3"; + amc->hw_strap1 = FUJI_BMC_HW_STRAP1; + amc->hw_strap2 = FUJI_BMC_HW_STRAP2; + amc->fmc_model = "mx66l1g45g"; + amc->spi_model = "mx66l1g45g"; + amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC3_ON; + amc->i2c_init = fuji_bmc_i2c_init; + amc->uart_default = ASPEED_DEV_UART1; + mc->default_ram_size = FUJI_BMC_RAM_SIZE; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); +}; + static const TypeInfo aspeed_machine_types[] = { { .name = MACHINE_TYPE_NAME("palmetto-bmc"), @@ -1072,6 +1236,10 @@ static const TypeInfo aspeed_machine_types[] = { .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_rainier_class_init, }, { + .name = MACHINE_TYPE_NAME("fuji-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_fuji_class_init, + }, { .name = TYPE_ASPEED_MACHINE, .parent = TYPE_MACHINE, .instance_size = sizeof(AspeedMachineState), diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index e301312..9d70e8e 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -322,10 +322,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); } - /* UART - attach an 8250 to the IO space as our UART5 */ - serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART5], 2, - aspeed_soc_get_irq(s, ASPEED_DEV_UART5), - 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN); + /* UART - attach an 8250 to the IO space as our UART */ + serial_mm_init(get_system_memory(), sc->memmap[s->uart_default], 2, + aspeed_soc_get_irq(s, s->uart_default), 38400, + serial_hd(0), DEVICE_LITTLE_ENDIAN); /* I2C */ object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr), @@ -516,9 +516,9 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) dc->realize = aspeed_soc_ast2600_realize; - sc->name = "ast2600-a1"; + sc->name = "ast2600-a3"; sc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"); - sc->silicon_rev = AST2600_A1_SILICON_REV; + sc->silicon_rev = AST2600_A3_SILICON_REV; sc->sram_size = 0x16400; sc->spis_num = 2; sc->ehcis_num = 2; @@ -530,7 +530,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) } static const TypeInfo aspeed_soc_ast2600_type_info = { - .name = "ast2600-a1", + .name = "ast2600-a3", .parent = TYPE_ASPEED_SOC, .instance_size = sizeof(AspeedSoCState), .instance_init = aspeed_soc_ast2600_init, diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 3ad6c56..ed84502 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -287,9 +287,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); } - /* UART - attach an 8250 to the IO space as our UART5 */ - serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART5], 2, - aspeed_soc_get_irq(s, ASPEED_DEV_UART5), 38400, + /* UART - attach an 8250 to the IO space as our UART */ + serial_mm_init(get_system_memory(), sc->memmap[s->uart_default], 2, + aspeed_soc_get_irq(s, s->uart_default), 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN); /* I2C */ @@ -439,6 +439,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) static Property aspeed_soc_properties[] = { DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_UINT32("uart-default", AspeedSoCState, uart_default, + ASPEED_DEV_UART5), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index b3dec44..dfa6d6c 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -164,49 +164,48 @@ #define GPIO_YZAAAB_DIRECTION (0x1E4 >> 2) #define GPIO_AC_DATA_VALUE (0x1E8 >> 2) #define GPIO_AC_DIRECTION (0x1EC >> 2) -#define GPIO_3_6V_MEM_SIZE 0x1F0 -#define GPIO_3_6V_REG_ARRAY_SIZE (GPIO_3_6V_MEM_SIZE >> 2) +#define GPIO_3_3V_MEM_SIZE 0x1F0 +#define GPIO_3_3V_REG_ARRAY_SIZE (GPIO_3_3V_MEM_SIZE >> 2) /* AST2600 only - 1.8V gpios */ /* - * The AST2600 has same 3.6V gpios as the AST2400 (memory offsets 0x0-0x198) - * and additional 1.8V gpios (memory offsets 0x800-0x9D4). + * The AST2600 two copies of the GPIO controller: the same 3.3V gpios as the + * AST2400 (memory offsets 0x0-0x198) and a second controller with 1.8V gpios + * (memory offsets 0x800-0x9D4). */ -#define GPIO_1_8V_REG_OFFSET 0x800 -#define GPIO_1_8V_ABCD_DATA_VALUE ((0x800 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_DIRECTION ((0x804 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_INT_ENABLE ((0x808 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_INT_SENS_0 ((0x80C - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_INT_SENS_1 ((0x810 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_INT_SENS_2 ((0x814 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_INT_STATUS ((0x818 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_RESET_TOLERANT ((0x81C - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_DATA_VALUE ((0x820 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_DIRECTION ((0x824 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_INT_ENABLE ((0x828 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_INT_SENS_0 ((0x82C - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_INT_SENS_1 ((0x830 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_INT_SENS_2 ((0x834 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_INT_STATUS ((0x838 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_RESET_TOLERANT ((0x83C - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_DEBOUNCE_1 ((0x840 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_DEBOUNCE_2 ((0x844 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_DEBOUNCE_1 ((0x848 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_DEBOUNCE_2 ((0x84C - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_DEBOUNCE_TIME_1 ((0x850 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_DEBOUNCE_TIME_2 ((0x854 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_DEBOUNCE_TIME_3 ((0x858 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_COMMAND_SRC_0 ((0x860 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_COMMAND_SRC_1 ((0x864 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_COMMAND_SRC_0 ((0x868 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_COMMAND_SRC_1 ((0x86C - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_DATA_READ ((0x8C0 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_DATA_READ ((0x8C4 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_ABCD_INPUT_MASK ((0x9D0 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_E_INPUT_MASK ((0x9D4 - GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_1_8V_MEM_SIZE 0x9D8 -#define GPIO_1_8V_REG_ARRAY_SIZE ((GPIO_1_8V_MEM_SIZE - \ - GPIO_1_8V_REG_OFFSET) >> 2) +#define GPIO_1_8V_ABCD_DATA_VALUE (0x000 >> 2) +#define GPIO_1_8V_ABCD_DIRECTION (0x004 >> 2) +#define GPIO_1_8V_ABCD_INT_ENABLE (0x008 >> 2) +#define GPIO_1_8V_ABCD_INT_SENS_0 (0x00C >> 2) +#define GPIO_1_8V_ABCD_INT_SENS_1 (0x010 >> 2) +#define GPIO_1_8V_ABCD_INT_SENS_2 (0x014 >> 2) +#define GPIO_1_8V_ABCD_INT_STATUS (0x018 >> 2) +#define GPIO_1_8V_ABCD_RESET_TOLERANT (0x01C >> 2) +#define GPIO_1_8V_E_DATA_VALUE (0x020 >> 2) +#define GPIO_1_8V_E_DIRECTION (0x024 >> 2) +#define GPIO_1_8V_E_INT_ENABLE (0x028 >> 2) +#define GPIO_1_8V_E_INT_SENS_0 (0x02C >> 2) +#define GPIO_1_8V_E_INT_SENS_1 (0x030 >> 2) +#define GPIO_1_8V_E_INT_SENS_2 (0x034 >> 2) +#define GPIO_1_8V_E_INT_STATUS (0x038 >> 2) +#define GPIO_1_8V_E_RESET_TOLERANT (0x03C >> 2) +#define GPIO_1_8V_ABCD_DEBOUNCE_1 (0x040 >> 2) +#define GPIO_1_8V_ABCD_DEBOUNCE_2 (0x044 >> 2) +#define GPIO_1_8V_E_DEBOUNCE_1 (0x048 >> 2) +#define GPIO_1_8V_E_DEBOUNCE_2 (0x04C >> 2) +#define GPIO_1_8V_DEBOUNCE_TIME_1 (0x050 >> 2) +#define GPIO_1_8V_DEBOUNCE_TIME_2 (0x054 >> 2) +#define GPIO_1_8V_DEBOUNCE_TIME_3 (0x058 >> 2) +#define GPIO_1_8V_ABCD_COMMAND_SRC_0 (0x060 >> 2) +#define GPIO_1_8V_ABCD_COMMAND_SRC_1 (0x064 >> 2) +#define GPIO_1_8V_E_COMMAND_SRC_0 (0x068 >> 2) +#define GPIO_1_8V_E_COMMAND_SRC_1 (0x06C >> 2) +#define GPIO_1_8V_ABCD_DATA_READ (0x0C0 >> 2) +#define GPIO_1_8V_E_DATA_READ (0x0C4 >> 2) +#define GPIO_1_8V_ABCD_INPUT_MASK (0x1D0 >> 2) +#define GPIO_1_8V_E_INPUT_MASK (0x1D4 >> 2) +#define GPIO_1_8V_MEM_SIZE 0x1D8 +#define GPIO_1_8V_REG_ARRAY_SIZE (GPIO_1_8V_MEM_SIZE >> 2) static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio) { @@ -381,7 +380,7 @@ static uint32_t update_value_control_source(GPIOSets *regs, uint32_t old_value, return new_value; } -static const AspeedGPIOReg aspeed_3_6v_gpios[GPIO_3_6V_REG_ARRAY_SIZE] = { +static const AspeedGPIOReg aspeed_3_3v_gpios[GPIO_3_3V_REG_ARRAY_SIZE] = { /* Set ABCD */ [GPIO_ABCD_DATA_VALUE] = { 0, gpio_reg_data_value }, [GPIO_ABCD_DIRECTION] = { 0, gpio_reg_direction }, @@ -801,7 +800,7 @@ static const GPIOSetProperties ast2500_set_props[] = { [7] = {0x000000ff, 0x000000ff, {"AC"} }, }; -static GPIOSetProperties ast2600_3_6v_set_props[] = { +static GPIOSetProperties ast2600_3_3v_set_props[] = { [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} }, [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} }, [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} }, @@ -928,7 +927,7 @@ static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 216; agc->nr_gpio_sets = 7; agc->gap = 196; - agc->reg_table = aspeed_3_6v_gpios; + agc->reg_table = aspeed_3_3v_gpios; } static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data) @@ -939,17 +938,17 @@ static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 228; agc->nr_gpio_sets = 8; agc->gap = 220; - agc->reg_table = aspeed_3_6v_gpios; + agc->reg_table = aspeed_3_3v_gpios; } -static void aspeed_gpio_ast2600_3_6v_class_init(ObjectClass *klass, void *data) +static void aspeed_gpio_ast2600_3_3v_class_init(ObjectClass *klass, void *data) { AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass); - agc->props = ast2600_3_6v_set_props; + agc->props = ast2600_3_3v_set_props; agc->nr_gpio_pins = 208; agc->nr_gpio_sets = 7; - agc->reg_table = aspeed_3_6v_gpios; + agc->reg_table = aspeed_3_3v_gpios; } static void aspeed_gpio_ast2600_1_8v_class_init(ObjectClass *klass, void *data) @@ -985,10 +984,10 @@ static const TypeInfo aspeed_gpio_ast2500_info = { .instance_init = aspeed_gpio_init, }; -static const TypeInfo aspeed_gpio_ast2600_3_6v_info = { +static const TypeInfo aspeed_gpio_ast2600_3_3v_info = { .name = TYPE_ASPEED_GPIO "-ast2600", .parent = TYPE_ASPEED_GPIO, - .class_init = aspeed_gpio_ast2600_3_6v_class_init, + .class_init = aspeed_gpio_ast2600_3_3v_class_init, .instance_init = aspeed_gpio_init, }; @@ -1004,7 +1003,7 @@ static void aspeed_gpio_register_types(void) type_register_static(&aspeed_gpio_info); type_register_static(&aspeed_gpio_ast2400_info); type_register_static(&aspeed_gpio_ast2500_info); - type_register_static(&aspeed_gpio_ast2600_3_6v_info); + type_register_static(&aspeed_gpio_ast2600_3_3v_info); type_register_static(&aspeed_gpio_ast2600_1_8v_info); } diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 40a38eb..d06e179 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -101,14 +101,26 @@ #define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84) #define AST2600_CLK_STOP_CTRL2 TO_REG(0x90) #define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94) +#define AST2600_DEBUG_CTRL TO_REG(0xC8) +#define AST2600_DEBUG_CTRL2 TO_REG(0xD8) #define AST2600_SDRAM_HANDSHAKE TO_REG(0x100) #define AST2600_HPLL_PARAM TO_REG(0x200) #define AST2600_HPLL_EXT TO_REG(0x204) +#define AST2600_APLL_PARAM TO_REG(0x210) +#define AST2600_APLL_EXT TO_REG(0x214) +#define AST2600_MPLL_PARAM TO_REG(0x220) #define AST2600_MPLL_EXT TO_REG(0x224) +#define AST2600_EPLL_PARAM TO_REG(0x240) #define AST2600_EPLL_EXT TO_REG(0x244) +#define AST2600_DPLL_PARAM TO_REG(0x260) +#define AST2600_DPLL_EXT TO_REG(0x264) #define AST2600_CLK_SEL TO_REG(0x300) #define AST2600_CLK_SEL2 TO_REG(0x304) -#define AST2600_CLK_SEL3 TO_REG(0x310) +#define AST2600_CLK_SEL3 TO_REG(0x308) +#define AST2600_CLK_SEL4 TO_REG(0x310) +#define AST2600_CLK_SEL5 TO_REG(0x314) +#define AST2600_UARTCLK TO_REG(0x338) +#define AST2600_HUARTCLK TO_REG(0x33C) #define AST2600_HW_STRAP1 TO_REG(0x500) #define AST2600_HW_STRAP1_CLR TO_REG(0x504) #define AST2600_HW_STRAP1_PROT TO_REG(0x508) @@ -433,6 +445,8 @@ static uint32_t aspeed_silicon_revs[] = { AST2500_A1_SILICON_REV, AST2600_A0_SILICON_REV, AST2600_A1_SILICON_REV, + AST2600_A2_SILICON_REV, + AST2600_A3_SILICON_REV, }; bool is_supported_silicon_rev(uint32_t silicon_rev) @@ -651,16 +665,28 @@ static const MemoryRegionOps aspeed_ast2600_scu_ops = { .valid.unaligned = false, }; -static const uint32_t ast2600_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = { +static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = { [AST2600_SYS_RST_CTRL] = 0xF7C3FED8, - [AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC, + [AST2600_SYS_RST_CTRL2] = 0x0DFFFFFC, [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A, [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0, + [AST2600_DEBUG_CTRL] = 0x00000FFF, + [AST2600_DEBUG_CTRL2] = 0x000000FF, [AST2600_SDRAM_HANDSHAKE] = 0x00000000, - [AST2600_HPLL_PARAM] = 0x1000405F, + [AST2600_HPLL_PARAM] = 0x1000408F, + [AST2600_APLL_PARAM] = 0x1000405F, + [AST2600_MPLL_PARAM] = 0x1008405F, + [AST2600_EPLL_PARAM] = 0x1004077F, + [AST2600_DPLL_PARAM] = 0x1078405F, + [AST2600_CLK_SEL] = 0xF3940000, + [AST2600_CLK_SEL2] = 0x00700000, + [AST2600_CLK_SEL3] = 0x00000000, + [AST2600_CLK_SEL4] = 0xF3F40000, + [AST2600_CLK_SEL5] = 0x30000000, + [AST2600_UARTCLK] = 0x00014506, + [AST2600_HUARTCLK] = 0x000145C0, [AST2600_CHIP_ID0] = 0x1234ABCD, [AST2600_CHIP_ID1] = 0x88884444, - }; static void aspeed_ast2600_scu_reset(DeviceState *dev) @@ -675,7 +701,7 @@ static void aspeed_ast2600_scu_reset(DeviceState *dev) * of actual revision. QEMU and Linux only support A1 onwards so this is * sufficient. */ - s->regs[AST2600_SILICON_REV] = AST2600_A1_SILICON_REV; + s->regs[AST2600_SILICON_REV] = AST2600_A3_SILICON_REV; s->regs[AST2600_SILICON_REV2] = s->silicon_rev; s->regs[AST2600_HW_STRAP1] = s->hw_strap1; s->regs[AST2600_HW_STRAP2] = s->hw_strap2; @@ -689,7 +715,7 @@ static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data) dc->desc = "ASPEED 2600 System Control Unit"; dc->reset = aspeed_ast2600_scu_reset; - asc->resets = ast2600_a1_resets; + asc->resets = ast2600_a3_resets; asc->calc_hpll = aspeed_2500_scu_calc_hpll; /* No change since AST2500 */ asc->apb_divider = 4; asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS; diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c index b7686e2..fff19e3 100644 --- a/hw/misc/pca9552.c +++ b/hw/misc/pca9552.c @@ -272,7 +272,7 @@ static void pca955x_get_led(Object *obj, Visitor *v, const char *name, * reading the INPUTx reg */ reg = PCA9552_LS0 + led / 4; - state = (pca955x_read(s, reg) >> (led % 8)) & 0x3; + state = (pca955x_read(s, reg) >> ((led % 4) * 2)) & 0x3; visit_type_str(v, name, (char **)&led_state[state], errp); } diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig index a2b55a4..9c8a049 100644 --- a/hw/sensor/Kconfig +++ b/hw/sensor/Kconfig @@ -6,6 +6,10 @@ config TMP421 bool depends on I2C +config DPS310 + bool + depends on I2C + config EMC141X bool depends on I2C diff --git a/hw/sensor/dps310.c b/hw/sensor/dps310.c new file mode 100644 index 0000000..d60a18a --- /dev/null +++ b/hw/sensor/dps310.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2017-2021 Joel Stanley <joel@jms.id.au>, IBM Corporation + * + * Infineon DPS310 temperature and humidity sensor + * + * https://www.infineon.com/cms/en/product/sensor/pressure-sensors/pressure-sensors-for-iot/dps310/ + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/hw.h" +#include "hw/i2c/i2c.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" + +#define NUM_REGISTERS 0x33 + +typedef struct DPS310State { + /*< private >*/ + I2CSlave i2c; + + /*< public >*/ + uint8_t regs[NUM_REGISTERS]; + + uint8_t len; + uint8_t pointer; + +} DPS310State; + +#define TYPE_DPS310 "dps310" +#define DPS310(obj) OBJECT_CHECK(DPS310State, (obj), TYPE_DPS310) + +#define DPS310_PRS_B2 0x00 +#define DPS310_PRS_B1 0x01 +#define DPS310_PRS_B0 0x02 +#define DPS310_TMP_B2 0x03 +#define DPS310_TMP_B1 0x04 +#define DPS310_TMP_B0 0x05 +#define DPS310_PRS_CFG 0x06 +#define DPS310_TMP_CFG 0x07 +#define DPS310_TMP_RATE_BITS (0x70) +#define DPS310_MEAS_CFG 0x08 +#define DPS310_MEAS_CTRL_BITS (0x07) +#define DPS310_PRESSURE_EN BIT(0) +#define DPS310_TEMP_EN BIT(1) +#define DPS310_BACKGROUND BIT(2) +#define DPS310_PRS_RDY BIT(4) +#define DPS310_TMP_RDY BIT(5) +#define DPS310_SENSOR_RDY BIT(6) +#define DPS310_COEF_RDY BIT(7) +#define DPS310_CFG_REG 0x09 +#define DPS310_RESET 0x0c +#define DPS310_RESET_MAGIC (BIT(0) | BIT(3)) +#define DPS310_COEF_BASE 0x10 +#define DPS310_COEF_LAST 0x21 +#define DPS310_COEF_SRC 0x28 + +static void dps310_reset(DeviceState *dev) +{ + DPS310State *s = DPS310(dev); + + static const uint8_t regs_reset_state[sizeof(s->regs)] = { + 0xfe, 0x2f, 0xee, 0x02, 0x69, 0xa6, 0x00, 0x80, 0xc7, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x0e, 0x1e, 0xdd, 0x13, 0xca, 0x5f, 0x21, 0x52, + 0xf9, 0xc6, 0x04, 0xd1, 0xdb, 0x47, 0x00, 0x5b, 0xfb, 0x3a, 0x00, 0x00, + 0x20, 0x49, 0x4e, 0xa5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x15, 0x02 + }; + + memcpy(s->regs, regs_reset_state, sizeof(s->regs)); + s->pointer = 0; + + /* TODO: assert these after some timeout ? */ + s->regs[DPS310_MEAS_CFG] = DPS310_COEF_RDY | DPS310_SENSOR_RDY + | DPS310_TMP_RDY | DPS310_PRS_RDY; +} + +static uint8_t dps310_read(DPS310State *s, uint8_t reg) +{ + if (reg >= sizeof(s->regs)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: register 0x%02x out of bounds\n", + __func__, s->pointer); + return 0xFF; + } + + switch (reg) { + case DPS310_PRS_B2: + case DPS310_PRS_B1: + case DPS310_PRS_B0: + case DPS310_TMP_B2: + case DPS310_TMP_B1: + case DPS310_TMP_B0: + case DPS310_PRS_CFG: + case DPS310_TMP_CFG: + case DPS310_MEAS_CFG: + case DPS310_CFG_REG: + case DPS310_COEF_BASE...DPS310_COEF_LAST: + case DPS310_COEF_SRC: + case 0x32: /* Undocumented register to indicate workaround not required */ + return s->regs[reg]; + default: + qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n", + __func__, reg); + return 0xFF; + } +} + +static void dps310_write(DPS310State *s, uint8_t reg, uint8_t data) +{ + if (reg >= sizeof(s->regs)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: register %d out of bounds\n", + __func__, s->pointer); + return; + } + + switch (reg) { + case DPS310_RESET: + if (data == DPS310_RESET_MAGIC) { + device_cold_reset(DEVICE(s)); + } + break; + case DPS310_PRS_CFG: + case DPS310_TMP_CFG: + case DPS310_MEAS_CFG: + case DPS310_CFG_REG: + s->regs[reg] = data; + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n", + __func__, reg); + return; + } +} + +static uint8_t dps310_rx(I2CSlave *i2c) +{ + DPS310State *s = DPS310(i2c); + + if (s->len == 1) { + return dps310_read(s, s->pointer++); + } else { + return 0xFF; + } +} + +static int dps310_tx(I2CSlave *i2c, uint8_t data) +{ + DPS310State *s = DPS310(i2c); + + if (s->len == 0) { + /* + * first byte is the register pointer for a read or write + * operation + */ + s->pointer = data; + s->len++; + } else if (s->len == 1) { + dps310_write(s, s->pointer++, data); + } + + return 0; +} + +static int dps310_event(I2CSlave *i2c, enum i2c_event event) +{ + DPS310State *s = DPS310(i2c); + + switch (event) { + case I2C_START_SEND: + s->pointer = 0xFF; + s->len = 0; + break; + case I2C_START_RECV: + if (s->len != 1) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid recv sequence\n", + __func__); + } + break; + default: + break; + } + + return 0; +} + +static const VMStateDescription vmstate_dps310 = { + .name = "DPS310", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8(len, DPS310State), + VMSTATE_UINT8_ARRAY(regs, DPS310State, NUM_REGISTERS), + VMSTATE_UINT8(pointer, DPS310State), + VMSTATE_I2C_SLAVE(i2c, DPS310State), + VMSTATE_END_OF_LIST() + } +}; + +static void dps310_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); + + k->event = dps310_event; + k->recv = dps310_rx; + k->send = dps310_tx; + dc->reset = dps310_reset; + dc->vmsd = &vmstate_dps310; +} + +static const TypeInfo dps310_info = { + .name = TYPE_DPS310, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(DPS310State), + .class_init = dps310_class_init, +}; + +static void dps310_register_types(void) +{ + type_register_static(&dps310_info); +} + +type_init(dps310_register_types) diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build index 034e3e0..059c4ca 100644 --- a/hw/sensor/meson.build +++ b/hw/sensor/meson.build @@ -1,5 +1,6 @@ softmmu_ss.add(when: 'CONFIG_TMP105', if_true: files('tmp105.c')) softmmu_ss.add(when: 'CONFIG_TMP421', if_true: files('tmp421.c')) +softmmu_ss.add(when: 'CONFIG_DPS310', if_true: files('dps310.c')) softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c')) softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('adm1272.c')) softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c')) diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c index 6352ba1..69c37af 100644 --- a/hw/watchdog/wdt_aspeed.c +++ b/hw/watchdog/wdt_aspeed.c @@ -118,13 +118,27 @@ static void aspeed_wdt_reload_1mhz(AspeedWDTState *s) } } +static uint64_t aspeed_2400_sanitize_ctrl(uint64_t data) +{ + return data & 0xffff; +} + +static uint64_t aspeed_2500_sanitize_ctrl(uint64_t data) +{ + return (data & ~(0xfUL << 8)) | WDT_CTRL_1MHZ_CLK; +} + +static uint64_t aspeed_2600_sanitize_ctrl(uint64_t data) +{ + return data & ~(0x7UL << 7); +} static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data, unsigned size) { AspeedWDTState *s = ASPEED_WDT(opaque); AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(s); - bool enable = data & WDT_CTRL_ENABLE; + bool enable; offset >>= 2; @@ -144,12 +158,16 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data, } break; case WDT_CTRL: + data = awc->sanitize_ctrl(data); + enable = data & WDT_CTRL_ENABLE; if (enable && !aspeed_wdt_is_enabled(s)) { s->regs[WDT_CTRL] = data; awc->wdt_reload(s); } else if (!enable && aspeed_wdt_is_enabled(s)) { s->regs[WDT_CTRL] = data; timer_del(s->timer); + } else { + s->regs[WDT_CTRL] = data; } break; case WDT_RESET_WIDTH: @@ -207,11 +225,12 @@ static const MemoryRegionOps aspeed_wdt_ops = { static void aspeed_wdt_reset(DeviceState *dev) { AspeedWDTState *s = ASPEED_WDT(dev); + AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(s); s->regs[WDT_STATUS] = 0x3EF1480; s->regs[WDT_RELOAD_VALUE] = 0x03EF1480; s->regs[WDT_RESTART] = 0; - s->regs[WDT_CTRL] = 0; + s->regs[WDT_CTRL] = awc->sanitize_ctrl(0); s->regs[WDT_RESET_WIDTH] = 0xFF; timer_del(s->timer); @@ -293,6 +312,7 @@ static void aspeed_2400_wdt_class_init(ObjectClass *klass, void *data) awc->ext_pulse_width_mask = 0xff; awc->reset_ctrl_reg = SCU_RESET_CONTROL1; awc->wdt_reload = aspeed_wdt_reload; + awc->sanitize_ctrl = aspeed_2400_sanitize_ctrl; } static const TypeInfo aspeed_2400_wdt_info = { @@ -328,6 +348,7 @@ static void aspeed_2500_wdt_class_init(ObjectClass *klass, void *data) awc->reset_ctrl_reg = SCU_RESET_CONTROL1; awc->reset_pulse = aspeed_2500_wdt_reset_pulse; awc->wdt_reload = aspeed_wdt_reload_1mhz; + awc->sanitize_ctrl = aspeed_2500_sanitize_ctrl; } static const TypeInfo aspeed_2500_wdt_info = { @@ -348,6 +369,7 @@ static void aspeed_2600_wdt_class_init(ObjectClass *klass, void *data) awc->reset_ctrl_reg = AST2600_SCU_RESET_CONTROL1; awc->reset_pulse = aspeed_2500_wdt_reset_pulse; awc->wdt_reload = aspeed_wdt_reload_1mhz; + awc->sanitize_ctrl = aspeed_2600_sanitize_ctrl; } static const TypeInfo aspeed_2600_wdt_info = { |