From 3d393bb7d3348142868d2af651500949881d41f0 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 01/15] docs: add minibmc section in aspeed document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Message-Id: <20220506031521.13254-2-jamin_lin@aspeedtech.com> Signed-off-by: Cédric Le Goater --- docs/system/arm/aspeed.rst | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index 60ed94f187..6f2e4fb53d 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -120,3 +120,64 @@ FMC chip and a bigger (64M) SPI chip, use : .. code-block:: bash -M ast2500-evb,fmc-model=mx25l25635e,spi-model=mx66u51235f + + +Aspeed minibmc family boards (``ast1030-evb``) +================================================================== + +The QEMU Aspeed machines model mini BMCs of various Aspeed evaluation +boards. They are based on different releases of the +Aspeed SoC : the AST1030 integrating an ARM Cortex M4F CPU (200MHz). + +The SoC comes with SRAM, SPI, I2C, etc. + +AST1030 SoC based machines : + +- ``ast1030-evb`` Aspeed AST1030 Evaluation board (Cortex-M4F) + +Supported devices +----------------- + + * SMP (for the AST1030 Cortex-M4F) + * Interrupt Controller (VIC) + * Timer Controller + * I2C Controller + * System Control Unit (SCU) + * SRAM mapping + * Static Memory Controller (SMC or FMC) - Only SPI Flash support + * SPI Memory Controller + * USB 2.0 Controller + * Watchdog Controller + * GPIO Controller (Master only) + * UART + * LPC Peripheral Controller (a subset of subdevices are supported) + * Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA + * ADC + + +Missing devices +--------------- + + * PWM and Fan Controller + * Slave GPIO Controller + * PECI Controller + * Mailbox Controller + * Virtual UART + * eSPI Controller + * I3C Controller + +Boot options +------------ + +The Aspeed machines can be started using the ``-kernel`` to load a +Zephyr OS or from a firmware. Images can be downloaded from the +ASPEED GitHub release repository : + + https://github.com/AspeedTech-BMC/zephyr/releases + +To boot a kernel directly from a Zephyr build tree: + +.. code-block:: bash + + $ qemu-system-arm -M ast1030-evb -nographic \ + -kernel zephyr.elf From fa699e80a80950ed31661dc8ea36a8b9aee9b094 Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 02/15] hw/arm/aspeed: Add fby35 machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the 'fby35-bmc' machine type based on the kernel DTS[1] and userspace i2c setup scripts[2]. Undefined values are inherited from the AST2600-EVB. Reference images can be found in Facebook OpenBMC Github Release assets as "fby35.mtd". [3] You can boot the reference images as follows (fby35 uses dual-flash): qemu-system-arm -machine fby35-bmc \ -drive file=fby35.mtd,format=raw,if=mtd \ -drive file=fby35.mtd,format=raw,if=mtd \ -nographic [1] https://github.com/facebook/openbmc-linux/blob/412d5053258007117e94b1e36015aefc1301474b/arch/arm/boot/dts/aspeed-bmc-facebook-fby35.dts [2] https://github.com/facebook/openbmc/blob/e2294ff5d31dd65c248fe396a385286d6d5c463d/meta-facebook/meta-fby35/recipes-fby35/plat-utils/files/setup-dev.sh [3] https://github.com/facebook/openbmc/releases Signed-off-by: Peter Delevoryas Reviewed-by: Cédric Le Goater Message-Id: <20220503225925.1798324-2-pdel@fb.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index a74c13ab0f..725c169488 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -21,6 +21,7 @@ #include "hw/misc/led.h" #include "hw/qdev-properties.h" #include "sysemu/block-backend.h" +#include "sysemu/reset.h" #include "hw/loader.h" #include "qemu/error-report.h" #include "qemu/units.h" @@ -951,6 +952,35 @@ static void bletchley_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(i2c[12], TYPE_PCA9552, 0x67); } +static void fby35_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + I2CBus *i2c[16]; + + for (int i = 0; i < 16; i++) { + i2c[i] = aspeed_i2c_get_bus(&soc->i2c, i); + } + + i2c_slave_create_simple(i2c[2], TYPE_LM75, 0x4f); + i2c_slave_create_simple(i2c[8], TYPE_TMP421, 0x1f); + /* Hotswap controller is actually supposed to be mp5920 or ltc4282. */ + i2c_slave_create_simple(i2c[11], "adm1272", 0x44); + i2c_slave_create_simple(i2c[12], TYPE_LM75, 0x4e); + i2c_slave_create_simple(i2c[12], TYPE_LM75, 0x4f); + + aspeed_eeprom_init(i2c[4], 0x51, 128 * KiB); + aspeed_eeprom_init(i2c[6], 0x51, 128 * KiB); + aspeed_eeprom_init(i2c[8], 0x50, 32 * KiB); + aspeed_eeprom_init(i2c[11], 0x51, 128 * KiB); + aspeed_eeprom_init(i2c[11], 0x54, 128 * KiB); + + /* + * TODO: There is a multi-master i2c connection to an AST1030 MiniBMC on + * buses 0, 1, 2, 3, and 9. Source address 0x10, target address 0x20 on + * each. + */ +} + static bool aspeed_get_mmio_exec(Object *obj, Error **errp) { return ASPEED_MACHINE(obj)->mmio_exec; @@ -1293,6 +1323,35 @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); } +static void fby35_reset(MachineState *state) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(state); + AspeedGPIOState *gpio = &bmc->soc.gpio; + + qemu_devices_reset(); + + /* Board ID */ + object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal); + object_property_set_bool(OBJECT(gpio), "gpioV5", true, &error_fatal); + object_property_set_bool(OBJECT(gpio), "gpioV6", true, &error_fatal); + object_property_set_bool(OBJECT(gpio), "gpioV7", false, &error_fatal); +} + +static void aspeed_machine_fby35_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook fby35 BMC (Cortex-A7)"; + mc->reset = fby35_reset; + amc->fmc_model = "mx66l1g45g"; + amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC3_ON; + amc->i2c_init = fby35_i2c_init; + /* FIXME: Replace this macro with something more general */ + mc->default_ram_size = FUJI_BMC_RAM_SIZE; +} + #define AST1030_INTERNAL_FLASH_SIZE (1024 * 1024) /* Main SYSCLK frequency in Hz (200MHz) */ #define SYSCLK_FRQ 200000000ULL @@ -1411,6 +1470,10 @@ static const TypeInfo aspeed_machine_types[] = { .name = MACHINE_TYPE_NAME("bletchley-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_bletchley_class_init, + }, { + .name = MACHINE_TYPE_NAME("fby35-bmc"), + .parent = MACHINE_TYPE_NAME("ast2600-evb"), + .class_init = aspeed_machine_fby35_class_init, }, { .name = MACHINE_TYPE_NAME("ast1030-evb"), .parent = TYPE_ASPEED_MACHINE, From 264a360ae0981a22e35b3e68b3eded1cac666afd Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 03/15] docs: aspeed: Add fby35 board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add fby35 to the list of Aspeed boards. Signed-off-by: Peter Delevoryas Message-Id: <20220506193354.990532-2-pdel@fb.com> Signed-off-by: Cédric Le Goater --- docs/system/arm/aspeed.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index 6f2e4fb53d..5d0a7865d3 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -31,6 +31,7 @@ AST2600 SoC based machines : - ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC - ``rainier-bmc`` IBM Rainier POWER10 BMC - ``fuji-bmc`` Facebook Fuji BMC +- ``fby35-bmc`` Facebook fby35 BMC Supported devices ----------------- From 188052a13377ff1f88b433255005eb9082d048e5 Mon Sep 17 00:00:00 2001 From: Iris Chen Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 04/15] hw: m25p80: allow write_enable latch get/set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The write_enable latch property is not currently exposed. This commit makes it a modifiable property. Signed-off-by: Iris Chen Acked-by: Thomas Huth Reviewed-by: Cédric Le Goater Reviewed-by: Francisco Iglesias Message-Id: <20220513055022.951759-1-irischenlj@fb.com> Signed-off-by: Cédric Le Goater --- hw/block/m25p80.c | 1 + tests/qtest/aspeed_gpio-test.c | 40 +++++++------------------------ tests/qtest/aspeed_smc-test.c | 43 ++++++++++++++++++++++++++++++++++ tests/qtest/libqtest.c | 24 +++++++++++++++++++ tests/qtest/libqtest.h | 22 +++++++++++++++++ 5 files changed, 98 insertions(+), 32 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 7d3d8b12e0..81ba3da4df 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -1533,6 +1533,7 @@ static int m25p80_pre_save(void *opaque) static Property m25p80_properties[] = { /* This is default value for Micron flash */ + DEFINE_PROP_BOOL("write-enable", Flash, write_enable, false), DEFINE_PROP_UINT32("nonvolatile-cfg", Flash, nonvolatile_cfg, 0x8FFF), DEFINE_PROP_UINT8("spansion-cr1nv", Flash, spansion_cr1nv, 0x0), DEFINE_PROP_UINT8("spansion-cr2nv", Flash, spansion_cr2nv, 0x8), diff --git a/tests/qtest/aspeed_gpio-test.c b/tests/qtest/aspeed_gpio-test.c index c1003f2d1b..bac63e8742 100644 --- a/tests/qtest/aspeed_gpio-test.c +++ b/tests/qtest/aspeed_gpio-test.c @@ -28,30 +28,6 @@ #include "qapi/qmp/qdict.h" #include "libqtest-single.h" -static bool qom_get_bool(QTestState *s, const char *path, const char *property) -{ - QDict *r; - bool b; - - r = qtest_qmp(s, "{ 'execute': 'qom-get', 'arguments': " - "{ 'path': %s, 'property': %s } }", path, property); - b = qdict_get_bool(r, "return"); - qobject_unref(r); - - return b; -} - -static void qom_set_bool(QTestState *s, const char *path, const char *property, - bool value) -{ - QDict *r; - - r = qtest_qmp(s, "{ 'execute': 'qom-set', 'arguments': " - "{ 'path': %s, 'property': %s, 'value': %i } }", - path, property, value); - qobject_unref(r); -} - static void test_set_colocated_pins(const void *data) { QTestState *s = (QTestState *)data; @@ -60,14 +36,14 @@ static void test_set_colocated_pins(const void *data) * gpioV4-7 occupy bits within a single 32-bit value, so we want to make * sure that modifying one doesn't affect the other. */ - qom_set_bool(s, "/machine/soc/gpio", "gpioV4", true); - qom_set_bool(s, "/machine/soc/gpio", "gpioV5", false); - qom_set_bool(s, "/machine/soc/gpio", "gpioV6", true); - qom_set_bool(s, "/machine/soc/gpio", "gpioV7", false); - g_assert(qom_get_bool(s, "/machine/soc/gpio", "gpioV4")); - g_assert(!qom_get_bool(s, "/machine/soc/gpio", "gpioV5")); - g_assert(qom_get_bool(s, "/machine/soc/gpio", "gpioV6")); - g_assert(!qom_get_bool(s, "/machine/soc/gpio", "gpioV7")); + qtest_qom_set_bool(s, "/machine/soc/gpio", "gpioV4", true); + qtest_qom_set_bool(s, "/machine/soc/gpio", "gpioV5", false); + qtest_qom_set_bool(s, "/machine/soc/gpio", "gpioV6", true); + qtest_qom_set_bool(s, "/machine/soc/gpio", "gpioV7", false); + g_assert(qtest_qom_get_bool(s, "/machine/soc/gpio", "gpioV4")); + g_assert(!qtest_qom_get_bool(s, "/machine/soc/gpio", "gpioV5")); + g_assert(qtest_qom_get_bool(s, "/machine/soc/gpio", "gpioV6")); + g_assert(!qtest_qom_get_bool(s, "/machine/soc/gpio", "gpioV7")); } int main(int argc, char **argv) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index 87b40a0ef1..ec233315e6 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu/bswap.h" #include "libqtest-single.h" +#include "qemu/bitops.h" /* * ASPEED SPI Controller registers @@ -40,6 +41,7 @@ #define CTRL_FREADMODE 0x1 #define CTRL_WRITEMODE 0x2 #define CTRL_USERMODE 0x3 +#define SR_WEL BIT(1) #define ASPEED_FMC_BASE 0x1E620000 #define ASPEED_FLASH_BASE 0x20000000 @@ -49,6 +51,8 @@ */ enum { JEDEC_READ = 0x9f, + RDSR = 0x5, + WRDI = 0x4, BULK_ERASE = 0xc7, READ = 0x03, PP = 0x02, @@ -348,6 +352,44 @@ static void test_write_page_mem(void) flash_reset(); } +static void test_read_status_reg(void) +{ + uint8_t r; + + spi_conf(CONF_ENABLE_W0); + + spi_ctrl_start_user(); + writeb(ASPEED_FLASH_BASE, RDSR); + r = readb(ASPEED_FLASH_BASE); + spi_ctrl_stop_user(); + + g_assert_cmphex(r & SR_WEL, ==, 0); + g_assert(!qtest_qom_get_bool + (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + + spi_ctrl_start_user(); + writeb(ASPEED_FLASH_BASE, WREN); + writeb(ASPEED_FLASH_BASE, RDSR); + r = readb(ASPEED_FLASH_BASE); + spi_ctrl_stop_user(); + + g_assert_cmphex(r & SR_WEL, ==, SR_WEL); + g_assert(qtest_qom_get_bool + (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + + spi_ctrl_start_user(); + writeb(ASPEED_FLASH_BASE, WRDI); + writeb(ASPEED_FLASH_BASE, RDSR); + r = readb(ASPEED_FLASH_BASE); + spi_ctrl_stop_user(); + + g_assert_cmphex(r & SR_WEL, ==, 0); + g_assert(!qtest_qom_get_bool + (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + + flash_reset(); +} + static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX"; int main(int argc, char **argv) @@ -373,6 +415,7 @@ int main(int argc, char **argv) qtest_add_func("/ast2400/smc/write_page", test_write_page); qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem); qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem); + qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg); ret = g_test_run(); diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 2e49618454..8c159eacf5 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -1440,3 +1440,27 @@ void qtest_client_inproc_recv(void *opaque, const char *str) g_string_append(qts->rx, str); return; } + +void qtest_qom_set_bool(QTestState *s, const char *path, const char *property, + bool value) +{ + QDict *r; + + r = qtest_qmp(s, "{ 'execute': 'qom-set', 'arguments': " + "{ 'path': %s, 'property': %s, 'value': %i } }", + path, property, value); + qobject_unref(r); +} + +bool qtest_qom_get_bool(QTestState *s, const char *path, const char *property) +{ + QDict *r; + bool b; + + r = qtest_qmp(s, "{ 'execute': 'qom-get', 'arguments': " + "{ 'path': %s, 'property': %s } }", path, property); + b = qdict_get_bool(r, "return"); + qobject_unref(r); + + return b; +} diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index 4ab0cad326..94b187837d 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -783,4 +783,26 @@ QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch, void (*send)(void*, const char*)); void qtest_client_inproc_recv(void *opaque, const char *str); + +/** + * qtest_qom_set_bool: + * @s: QTestState instance to operate on. + * @path: Path to the property being set. + * @property: Property being set. + * @value: Value to set the property. + * + * Set the property with passed in value. + */ +void qtest_qom_set_bool(QTestState *s, const char *path, const char *property, + bool value); + +/** + * qtest_qom_get_bool: + * @s: QTestState instance to operate on. + * @path: Path to the property being retrieved. + * @property: Property from where the value is being retrieved. + * + * Returns: Value retrieved from property. + */ +bool qtest_qom_get_bool(QTestState *s, const char *path, const char *property); #endif From 699db71520502836efc0e9102b0ffa6b0e5d0758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 05/15] aspeed: Introduce a get_irq AspeedSoCClass method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and make routine aspeed_soc_get_irq() common to all SoCs. This will be useful to share code. Cc: Jamin Lin Cc: Peter Delevoryas Reviewed-by: Peter Delevoryas Signed-off-by: Cédric Le Goater Message-Id: <20220516055620.2380197-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast10x0.c | 5 +++-- hw/arm/aspeed_ast2600.c | 5 +++-- hw/arm/aspeed_soc.c | 13 ++++++++++--- include/hw/arm/aspeed_soc.h | 3 +++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index 4271549282..9ae9efaac1 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -61,11 +61,11 @@ static const int aspeed_soc_ast1030_irqmap[] = { [ASPEED_DEV_KCS] = 138, /* 138 -> 142 */ }; -static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) +static qemu_irq aspeed_soc_ast1030_get_irq(AspeedSoCState *s, int dev) { AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); - return qdev_get_gpio_in(DEVICE(&s->armv7m), sc->irqmap[ctrl]); + return qdev_get_gpio_in(DEVICE(&s->armv7m), sc->irqmap[dev]); } static void aspeed_soc_ast1030_init(Object *obj) @@ -280,6 +280,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; + sc->get_irq = aspeed_soc_ast1030_get_irq; } static const TypeInfo aspeed_soc_ast1030_type_info = { diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index eedda7badc..4161a0cc4b 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -114,11 +114,11 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_I3C] = 102, /* 102 -> 107 */ }; -static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) +static qemu_irq aspeed_soc_ast2600_get_irq(AspeedSoCState *s, int dev) { AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); - return qdev_get_gpio_in(DEVICE(&s->a7mpcore), sc->irqmap[ctrl]); + return qdev_get_gpio_in(DEVICE(&s->a7mpcore), sc->irqmap[dev]); } static void aspeed_soc_ast2600_init(Object *obj) @@ -572,6 +572,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) sc->irqmap = aspeed_soc_ast2600_irqmap; sc->memmap = aspeed_soc_ast2600_memmap; sc->num_cpus = 2; + sc->get_irq = aspeed_soc_ast2600_get_irq; } static const TypeInfo aspeed_soc_ast2600_type_info = { diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 58714cb2a0..c339b5c74d 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -121,11 +121,11 @@ static const int aspeed_soc_ast2400_irqmap[] = { #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap -static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) +static qemu_irq aspeed_soc_ast2400_get_irq(AspeedSoCState *s, int dev) { AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); - return qdev_get_gpio_in(DEVICE(&s->vic), sc->irqmap[ctrl]); + return qdev_get_gpio_in(DEVICE(&s->vic), sc->irqmap[dev]); } static void aspeed_soc_init(Object *obj) @@ -487,6 +487,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) sc->irqmap = aspeed_soc_ast2400_irqmap; sc->memmap = aspeed_soc_ast2400_memmap; sc->num_cpus = 1; + sc->get_irq = aspeed_soc_ast2400_get_irq; } static const TypeInfo aspeed_soc_ast2400_type_info = { @@ -512,6 +513,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) sc->irqmap = aspeed_soc_ast2500_irqmap; sc->memmap = aspeed_soc_ast2500_memmap; sc->num_cpus = 1; + sc->get_irq = aspeed_soc_ast2400_get_irq; } static const TypeInfo aspeed_soc_ast2500_type_info = { @@ -528,4 +530,9 @@ static void aspeed_soc_register_types(void) type_register_static(&aspeed_soc_ast2500_type_info); }; -type_init(aspeed_soc_register_types) +type_init(aspeed_soc_register_types); + +qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev) +{ + return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev); +} diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index e13af374b9..3789f38603 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -94,6 +94,7 @@ struct AspeedSoCClass { const int *irqmap; const hwaddr *memmap; uint32_t num_cpus; + qemu_irq (*get_irq)(AspeedSoCState *s, int dev); }; @@ -153,4 +154,6 @@ enum { ASPEED_DEV_I3C, }; +qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); + #endif /* ASPEED_SOC_H */ From ab5e86053d16721b5b92780e23bc3104fdcb1f05 Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 06/15] hw: aspeed: Add missing UART's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the missing UART memory and IRQ mappings for the AST2400, AST2500, AST2600, and AST1030. This also includes the new UART interfaces added in the AST2600 and AST1030 from UART6 to UART13. The addresses and interrupt numbers for these two later chips are identical. Signed-off-by: Peter Delevoryas Reviewed-by: Cédric Le Goater Message-Id: <20220516062328.298336-2-pdel@fb.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast10x0.c | 24 ++++++++++++++++++++++++ hw/arm/aspeed_ast2600.c | 19 +++++++++++++++++++ hw/arm/aspeed_soc.c | 6 ++++++ include/hw/arm/aspeed_soc.h | 8 ++++++++ 4 files changed, 57 insertions(+) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index 9ae9efaac1..fa2cc4406c 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -33,14 +33,38 @@ static const hwaddr aspeed_soc_ast1030_memmap[] = { [ASPEED_DEV_SBC] = 0x7E6F2000, [ASPEED_DEV_GPIO] = 0x7E780000, [ASPEED_DEV_TIMER1] = 0x7E782000, + [ASPEED_DEV_UART1] = 0x7E783000, + [ASPEED_DEV_UART2] = 0x7E78D000, + [ASPEED_DEV_UART3] = 0x7E78E000, + [ASPEED_DEV_UART4] = 0x7E78F000, [ASPEED_DEV_UART5] = 0x7E784000, + [ASPEED_DEV_UART6] = 0x7E790000, + [ASPEED_DEV_UART7] = 0x7E790100, + [ASPEED_DEV_UART8] = 0x7E790200, + [ASPEED_DEV_UART9] = 0x7E790300, + [ASPEED_DEV_UART10] = 0x7E790400, + [ASPEED_DEV_UART11] = 0x7E790500, + [ASPEED_DEV_UART12] = 0x7E790600, + [ASPEED_DEV_UART13] = 0x7E790700, [ASPEED_DEV_WDT] = 0x7E785000, [ASPEED_DEV_LPC] = 0x7E789000, [ASPEED_DEV_I2C] = 0x7E7B0000, }; static const int aspeed_soc_ast1030_irqmap[] = { + [ASPEED_DEV_UART1] = 47, + [ASPEED_DEV_UART2] = 48, + [ASPEED_DEV_UART3] = 49, + [ASPEED_DEV_UART4] = 50, [ASPEED_DEV_UART5] = 8, + [ASPEED_DEV_UART6] = 57, + [ASPEED_DEV_UART7] = 58, + [ASPEED_DEV_UART8] = 59, + [ASPEED_DEV_UART9] = 60, + [ASPEED_DEV_UART10] = 61, + [ASPEED_DEV_UART11] = 62, + [ASPEED_DEV_UART12] = 63, + [ASPEED_DEV_UART13] = 64, [ASPEED_DEV_GPIO] = 11, [ASPEED_DEV_TIMER1] = 16, [ASPEED_DEV_TIMER2] = 17, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 4161a0cc4b..f3ecc0f3b7 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -61,7 +61,18 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_IBT] = 0x1E789140, [ASPEED_DEV_I2C] = 0x1E78A000, [ASPEED_DEV_UART1] = 0x1E783000, + [ASPEED_DEV_UART2] = 0x1E78D000, + [ASPEED_DEV_UART3] = 0x1E78E000, + [ASPEED_DEV_UART4] = 0x1E78F000, [ASPEED_DEV_UART5] = 0x1E784000, + [ASPEED_DEV_UART6] = 0x1E790000, + [ASPEED_DEV_UART7] = 0x1E790100, + [ASPEED_DEV_UART8] = 0x1E790200, + [ASPEED_DEV_UART9] = 0x1E790300, + [ASPEED_DEV_UART10] = 0x1E790400, + [ASPEED_DEV_UART11] = 0x1E790500, + [ASPEED_DEV_UART12] = 0x1E790600, + [ASPEED_DEV_UART13] = 0x1E790700, [ASPEED_DEV_VUART] = 0x1E787000, [ASPEED_DEV_I3C] = 0x1E7A0000, [ASPEED_DEV_SDRAM] = 0x80000000, @@ -78,6 +89,14 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_UART3] = 49, [ASPEED_DEV_UART4] = 50, [ASPEED_DEV_UART5] = 8, + [ASPEED_DEV_UART6] = 57, + [ASPEED_DEV_UART7] = 58, + [ASPEED_DEV_UART8] = 59, + [ASPEED_DEV_UART9] = 60, + [ASPEED_DEV_UART10] = 61, + [ASPEED_DEV_UART11] = 62, + [ASPEED_DEV_UART12] = 63, + [ASPEED_DEV_UART13] = 64, [ASPEED_DEV_VUART] = 8, [ASPEED_DEV_FMC] = 39, [ASPEED_DEV_SDMC] = 0, diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index c339b5c74d..96bc060680 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -48,6 +48,9 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { [ASPEED_DEV_ETH1] = 0x1E660000, [ASPEED_DEV_ETH2] = 0x1E680000, [ASPEED_DEV_UART1] = 0x1E783000, + [ASPEED_DEV_UART2] = 0x1E78D000, + [ASPEED_DEV_UART3] = 0x1E78E000, + [ASPEED_DEV_UART4] = 0x1E78F000, [ASPEED_DEV_UART5] = 0x1E784000, [ASPEED_DEV_VUART] = 0x1E787000, [ASPEED_DEV_SDRAM] = 0x40000000, @@ -80,6 +83,9 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_DEV_ETH1] = 0x1E660000, [ASPEED_DEV_ETH2] = 0x1E680000, [ASPEED_DEV_UART1] = 0x1E783000, + [ASPEED_DEV_UART2] = 0x1E78D000, + [ASPEED_DEV_UART3] = 0x1E78E000, + [ASPEED_DEV_UART4] = 0x1E78F000, [ASPEED_DEV_UART5] = 0x1E784000, [ASPEED_DEV_VUART] = 0x1E787000, [ASPEED_DEV_SDRAM] = 0x80000000, diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 3789f38603..709a78285b 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -105,6 +105,14 @@ enum { ASPEED_DEV_UART3, ASPEED_DEV_UART4, ASPEED_DEV_UART5, + ASPEED_DEV_UART6, + ASPEED_DEV_UART7, + ASPEED_DEV_UART8, + ASPEED_DEV_UART9, + ASPEED_DEV_UART10, + ASPEED_DEV_UART11, + ASPEED_DEV_UART12, + ASPEED_DEV_UART13, ASPEED_DEV_VUART, ASPEED_DEV_FMC, ASPEED_DEV_SPI1, From c5e1bdb9e243ad5563196175415f42e459040367 Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 07/15] hw: aspeed: Add uarts_num SoC attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AST2400 and AST2500 have 5 UART's, while the AST2600 and AST1030 have 13. Signed-off-by: Peter Delevoryas Reviewed-by: Cédric Le Goater Message-Id: <20220516062328.298336-3-pdel@fb.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc.c | 2 ++ include/hw/arm/aspeed_soc.h | 1 + 4 files changed, 5 insertions(+) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index fa2cc4406c..bb8177e86c 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -301,6 +301,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->ehcis_num = 0; sc->wdts_num = 4; sc->macs_num = 1; + sc->uarts_num = 13; sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index f3ecc0f3b7..a9523074a0 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -588,6 +588,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) sc->ehcis_num = 2; sc->wdts_num = 4; sc->macs_num = 4; + sc->uarts_num = 13; sc->irqmap = aspeed_soc_ast2600_irqmap; sc->memmap = aspeed_soc_ast2600_memmap; sc->num_cpus = 2; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 96bc060680..7008cd1af7 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -490,6 +490,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) sc->ehcis_num = 1; sc->wdts_num = 2; sc->macs_num = 2; + sc->uarts_num = 5; sc->irqmap = aspeed_soc_ast2400_irqmap; sc->memmap = aspeed_soc_ast2400_memmap; sc->num_cpus = 1; @@ -516,6 +517,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) sc->ehcis_num = 2; sc->wdts_num = 3; sc->macs_num = 2; + sc->uarts_num = 5; sc->irqmap = aspeed_soc_ast2500_irqmap; sc->memmap = aspeed_soc_ast2500_memmap; sc->num_cpus = 1; diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 709a78285b..669bc49855 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -91,6 +91,7 @@ struct AspeedSoCClass { int ehcis_num; int wdts_num; int macs_num; + int uarts_num; const int *irqmap; const hwaddr *memmap; uint32_t num_cpus; From 94d10f42109a5ba23e26012722b16f0f479990cb Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 08/15] hw: aspeed: Ensure AST1030 respects uart-default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AST1030 machine initialization was not respecting the Aspeed SoC property "uart-default", which specifies which UART should be connected to the first serial device, it was just always connecting UART5. This doesn't change any behavior, because the default value for "uart-default" is UART5, but it makes it possible to override this in new machine definitions using the AST1030. Signed-off-by: Peter Delevoryas Reviewed-by: Cédric Le Goater Message-Id: <20220516062328.298336-4-pdel@fb.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast10x0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index bb8177e86c..faafb800f3 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -215,9 +215,9 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) qdev_get_gpio_in(DEVICE(&s->armv7m), sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4)); - /* UART5 - attach an 8250 to the IO space as our UART */ - serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART5], 2, - aspeed_soc_get_irq(s, ASPEED_DEV_UART5), + /* 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); /* Timer */ From 470253b6d05ecec4bf7c8f8616db779454414292 Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 09/15] hw: aspeed: Introduce common UART init function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Delevoryas Reviewed-by: Cédric Le Goater Message-Id: <20220516062328.298336-5-pdel@fb.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast10x0.c | 7 ++----- hw/arm/aspeed_ast2600.c | 7 ++----- hw/arm/aspeed_soc.c | 16 ++++++++++++---- include/hw/arm/aspeed_soc.h | 1 + 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index faafb800f3..938615d55f 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -15,7 +15,6 @@ #include "sysemu/sysemu.h" #include "hw/qdev-clock.h" #include "hw/misc/unimp.h" -#include "hw/char/serial.h" #include "hw/arm/aspeed_soc.h" #define ASPEED_SOC_IOMEM_SIZE 0x00200000 @@ -215,10 +214,8 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) qdev_get_gpio_in(DEVICE(&s->armv7m), sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4)); - /* 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); + /* UART */ + aspeed_soc_uart_init(s); /* Timer */ object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu), diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index a9523074a0..b0a4199b69 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -11,7 +11,6 @@ #include "qapi/error.h" #include "hw/misc/unimp.h" #include "hw/arm/aspeed_soc.h" -#include "hw/char/serial.h" #include "qemu/module.h" #include "qemu/error-report.h" #include "hw/i2c/aspeed_i2c.h" @@ -372,10 +371,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_ADC)); - /* 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); + /* UART */ + aspeed_soc_uart_init(s); /* I2C */ object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr), diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 7008cd1af7..912798a9c9 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -303,10 +303,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_ADC)); - /* 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); + /* UART */ + aspeed_soc_uart_init(s); /* I2C */ object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr), @@ -544,3 +542,13 @@ qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev) { return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev); } + +void aspeed_soc_uart_init(AspeedSoCState *s) +{ + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + + /* 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); +} diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 669bc49855..02a5a9ffcb 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -164,5 +164,6 @@ enum { }; qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); +void aspeed_soc_uart_init(AspeedSoCState *s); #endif /* ASPEED_SOC_H */ From 6827ff20b2975e84045ba356ba3e6aadc686a53c Mon Sep 17 00:00:00 2001 From: Peter Delevoryas Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 10/15] hw: aspeed: Init all UART's with serial devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Background: AspeedMachineClass.uart_default specifies the serial console UART, which usually corresponds to the "stdout-path" in the device tree. The default value is UART5, since most boards use UART5 for this: amc->uart_default = ASPEED_DEV_UART5; Users can override AspeedMachineClass.uart_default in their board's machine class init to specify something besides UART5. For example, for fuji-bmc: amc->uart_default = ASPEED_DEV_UART1; We only connect this one UART, of the 5 UART's on the AST2400 and AST2500 and the 13 UART's on the AST2600 and AST1030, to a serial device that QEMU users can use. None of the other UART's are initialized, and the only way to override this attribute is by creating a specialized board definition, requiring QEMU source code changes and rebuilding. The result of this is that if you want to get serial console output on a board that uses UART3, you need to add a board definition. This was encountered by Zev in OpenBMC. [1] Changes: This commit initializes all of the UART's present on each Aspeed chip with serial devices and allows the QEMU user to connect as many or few as they like to serial devices. For example, you can still run QEMU and just connect stdout to the machine's default UART, without specifying any additional serial devices: qemu-system-arm -machine fuji-bmc \ -drive file=fuji.mtd,format=raw,if=mtd \ -nographic However, if you don't want to add a special machine definition, you can now manually configure UART1 to connect to stdout and get serial console output, even if the machine's default is UART5: qemu-system-arm -machine ast2600-evb \ -drive file=fuji.mtd,format=raw,if=mtd \ -serial null -serial mon:stdio -display none In the example above, the first "-serial null" argument is connected to UART5, and "-serial mon:stdio" is connected to UART1. Another example: you can get serial console output from Wedge100, which uses UART3, by reusing the palmetto AST2400 machine and rewiring the serial device arguments: qemu-system-arm -machine palmetto-bmc \ -drive file=wedge100.mtd,format=raw,if=mtd \ -serial null -serial null -serial null \ -serial mon:stdio -display none There is a slight change in behavior introduced with this change: now, each UART's memory-mapped IO region will have a serial device model connected to it. Previously, all reads and writes to those regions would be ineffective and return zero values, but now some values will be nonzero, even when the user doesn't connect a serial device backend (like a socket, file, etc). For example, the line status register might indicate that the transmit buffer is empty now, whereas previously it might have always indicated it was full. [1] https://lore.kernel.org/openbmc/YnzGnWjkYdMUUNyM@hatter.bewilderbeest.net/ [2] https://github.com/facebook/openbmc/releases/download/v2021.49.0/fuji.mtd [3] https://github.com/facebook/openbmc/releases/download/v2021.49.0/wedge100.mtd Signed-off-by: Peter Delevoryas Reviewed-by: Cédric Le Goater Message-Id: <20220516062328.298336-6-pdel@fb.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_soc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 912798a9c9..30574d4276 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -546,9 +546,18 @@ qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev) void aspeed_soc_uart_init(AspeedSoCState *s) { AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + int i, 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); + for (i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { + if (uart == s->uart_default) { + uart++; + } + serial_mm_init(get_system_memory(), sc->memmap[uart], 2, + aspeed_soc_get_irq(s, uart), 38400, + serial_hd(i), DEVICE_LITTLE_ENDIAN); + } } From 7b1d21a8ba1e6091f1e54c74e7c664e26300accc Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 11/15] hw/gpio Add GPIO read/write trace event. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add GPIO read/write trace event for aspeed model. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Message-Id: <20220525053444.27228-2-jamin_lin@aspeedtech.com> Signed-off-by: Cédric Le Goater --- hw/gpio/aspeed_gpio.c | 54 +++++++++++++++++++++++++++++++------------ hw/gpio/trace-events | 4 ++++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index 9b736e7a9f..4620ea8e8b 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -15,6 +15,7 @@ #include "qapi/visitor.h" #include "hw/irq.h" #include "migration/vmstate.h" +#include "trace.h" #define GPIOS_PER_GROUP 8 @@ -523,11 +524,15 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size) uint64_t idx = -1; const AspeedGPIOReg *reg; GPIOSets *set; + uint32_t value = 0; + uint64_t debounce_value; idx = offset >> 2; if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) { idx -= GPIO_DEBOUNCE_TIME_1; - return (uint64_t) s->debounce_regs[idx]; + debounce_value = (uint64_t) s->debounce_regs[idx]; + trace_aspeed_gpio_read(offset, debounce_value); + return debounce_value; } reg = &agc->reg_table[idx]; @@ -540,38 +545,55 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size) set = &s->sets[reg->set_idx]; switch (reg->type) { case gpio_reg_data_value: - return set->data_value; + value = set->data_value; + break; case gpio_reg_direction: - return set->direction; + value = set->direction; + break; case gpio_reg_int_enable: - return set->int_enable; + value = set->int_enable; + break; case gpio_reg_int_sens_0: - return set->int_sens_0; + value = set->int_sens_0; + break; case gpio_reg_int_sens_1: - return set->int_sens_1; + value = set->int_sens_1; + break; case gpio_reg_int_sens_2: - return set->int_sens_2; + value = set->int_sens_2; + break; case gpio_reg_int_status: - return set->int_status; + value = set->int_status; + break; case gpio_reg_reset_tolerant: - return set->reset_tol; + value = set->reset_tol; + break; case gpio_reg_debounce_1: - return set->debounce_1; + value = set->debounce_1; + break; case gpio_reg_debounce_2: - return set->debounce_2; + value = set->debounce_2; + break; case gpio_reg_cmd_source_0: - return set->cmd_source_0; + value = set->cmd_source_0; + break; case gpio_reg_cmd_source_1: - return set->cmd_source_1; + value = set->cmd_source_1; + break; case gpio_reg_data_read: - return set->data_read; + value = set->data_read; + break; case gpio_reg_input_mask: - return set->input_mask; + value = set->input_mask; + break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%" HWADDR_PRIx"\n", __func__, offset); return 0; } + + trace_aspeed_gpio_read(offset, value); + return value; } static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, @@ -585,6 +607,8 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, GPIOSets *set; uint32_t cleared; + trace_aspeed_gpio_write(offset, data); + idx = offset >> 2; if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) { idx -= GPIO_DEBOUNCE_TIME_1; diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events index 1dab99c560..9736b362ac 100644 --- a/hw/gpio/trace-events +++ b/hw/gpio/trace-events @@ -27,3 +27,7 @@ sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" P sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 + +# aspeed_gpio.c +aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64 +aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64 From 17075ef244d4ca52f7f097927c72b0e09f8d8a5c Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 12/15] hw/gpio: Add ASPEED GPIO model for AST1030 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AST1030 integrates one set of Parallel GPIO Controller with maximum 151 control pins, which are 21 groups (A~U, exclude pin: M6 M7 Q5 Q6 Q7 R0 R1 R4 R5 R6 R7 S0 S3 S4 S5 S6 S7 ) and the group T and U are input only. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Message-Id: <20220525053444.27228-3-jamin_lin@aspeedtech.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast10x0.c | 11 +++++++++++ hw/gpio/aspeed_gpio.c | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index 938615d55f..d534541684 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -136,6 +136,9 @@ static void aspeed_soc_ast1030_init(Object *obj) snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename); } + + snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); + object_initialize_child(obj, "gpio", &s->gpio, typename); } static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) @@ -281,6 +284,14 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, sc->memmap[ASPEED_DEV_WDT] + i * awc->offset); } + + /* GPIO */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_DEV_GPIO]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_GPIO)); } static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index 4620ea8e8b..5138fe812b 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -819,6 +819,15 @@ static GPIOSetProperties ast2600_1_8v_set_props[ASPEED_GPIO_MAX_NR_SETS] = { [1] = {0x0000000f, 0x0000000f, {"18E"} }, }; +static GPIOSetProperties ast1030_set_props[ASPEED_GPIO_MAX_NR_SETS] = { + [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} }, + [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} }, + [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} }, + [3] = {0xffffff3f, 0xffffff3f, {"M", "N", "O", "P"} }, + [4] = {0xff060c1f, 0x00060c1f, {"Q", "R", "S", "T"} }, + [5] = {0x000000ff, 0x00000000, {"U"} }, +}; + static const MemoryRegionOps aspeed_gpio_ops = { .read = aspeed_gpio_read, .write = aspeed_gpio_write, @@ -971,6 +980,16 @@ static void aspeed_gpio_ast2600_1_8v_class_init(ObjectClass *klass, void *data) agc->reg_table = aspeed_1_8v_gpios; } +static void aspeed_gpio_1030_class_init(ObjectClass *klass, void *data) +{ + AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass); + + agc->props = ast1030_set_props; + agc->nr_gpio_pins = 151; + agc->nr_gpio_sets = 6; + agc->reg_table = aspeed_3_3v_gpios; +} + static const TypeInfo aspeed_gpio_info = { .name = TYPE_ASPEED_GPIO, .parent = TYPE_SYS_BUS_DEVICE, @@ -1008,6 +1027,13 @@ static const TypeInfo aspeed_gpio_ast2600_1_8v_info = { .instance_init = aspeed_gpio_init, }; +static const TypeInfo aspeed_gpio_ast1030_info = { + .name = TYPE_ASPEED_GPIO "-ast1030", + .parent = TYPE_ASPEED_GPIO, + .class_init = aspeed_gpio_1030_class_init, + .instance_init = aspeed_gpio_init, +}; + static void aspeed_gpio_register_types(void) { type_register_static(&aspeed_gpio_info); @@ -1015,6 +1041,7 @@ static void aspeed_gpio_register_types(void) type_register_static(&aspeed_gpio_ast2500_info); type_register_static(&aspeed_gpio_ast2600_3_3v_info); type_register_static(&aspeed_gpio_ast2600_1_8v_info); + type_register_static(&aspeed_gpio_ast1030_info); } type_init(aspeed_gpio_register_types); From 247c00294a4b3cc694f24811eef07e57eb67aa82 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 13/15] hw/gpio support GPIO index mode for write operation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It did not support GPIO index mode for read operation. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Message-Id: <20220525053444.27228-4-jamin_lin@aspeedtech.com> Signed-off-by: Cédric Le Goater --- hw/gpio/aspeed_gpio.c | 168 ++++++++++++++++++++++++++++++++++ include/hw/gpio/aspeed_gpio.h | 14 +++ 2 files changed, 182 insertions(+) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index 5138fe812b..c834bf19f5 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -16,6 +16,7 @@ #include "hw/irq.h" #include "migration/vmstate.h" #include "trace.h" +#include "hw/registerfields.h" #define GPIOS_PER_GROUP 8 @@ -204,6 +205,28 @@ #define GPIO_1_8V_MEM_SIZE 0x1D8 #define GPIO_1_8V_REG_ARRAY_SIZE (GPIO_1_8V_MEM_SIZE >> 2) +/* + * GPIO index mode support + * It only supports write operation + */ +REG32(GPIO_INDEX_REG, 0x2AC) + FIELD(GPIO_INDEX_REG, NUMBER, 0, 8) + FIELD(GPIO_INDEX_REG, COMMAND, 12, 1) + FIELD(GPIO_INDEX_REG, TYPE, 16, 4) + FIELD(GPIO_INDEX_REG, DATA_VALUE, 20, 1) + FIELD(GPIO_INDEX_REG, DIRECTION, 20, 1) + FIELD(GPIO_INDEX_REG, INT_ENABLE, 20, 1) + FIELD(GPIO_INDEX_REG, INT_SENS_0, 21, 1) + FIELD(GPIO_INDEX_REG, INT_SENS_1, 22, 1) + FIELD(GPIO_INDEX_REG, INT_SENS_2, 23, 1) + FIELD(GPIO_INDEX_REG, INT_STATUS, 24, 1) + FIELD(GPIO_INDEX_REG, DEBOUNCE_1, 20, 1) + FIELD(GPIO_INDEX_REG, DEBOUNCE_2, 21, 1) + FIELD(GPIO_INDEX_REG, RESET_TOLERANT, 20, 1) + FIELD(GPIO_INDEX_REG, COMMAND_SRC_0, 20, 1) + FIELD(GPIO_INDEX_REG, COMMAND_SRC_1, 21, 1) + FIELD(GPIO_INDEX_REG, INPUT_MASK, 20, 1) + static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio) { uint32_t falling_edge = 0, rising_edge = 0; @@ -596,6 +619,144 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size) return value; } +static void aspeed_gpio_write_index_mode(void *opaque, hwaddr offset, + uint64_t data, uint32_t size) +{ + + AspeedGPIOState *s = ASPEED_GPIO(opaque); + AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s); + const GPIOSetProperties *props; + GPIOSets *set; + uint32_t reg_idx_number = FIELD_EX32(data, GPIO_INDEX_REG, NUMBER); + uint32_t reg_idx_type = FIELD_EX32(data, GPIO_INDEX_REG, TYPE); + uint32_t reg_idx_command = FIELD_EX32(data, GPIO_INDEX_REG, COMMAND); + uint32_t set_idx = reg_idx_number / ASPEED_GPIOS_PER_SET; + uint32_t pin_idx = reg_idx_number % ASPEED_GPIOS_PER_SET; + uint32_t group_idx = pin_idx / GPIOS_PER_GROUP; + uint32_t reg_value = 0; + uint32_t cleared; + + set = &s->sets[set_idx]; + props = &agc->props[set_idx]; + + if (reg_idx_command) + qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%" PRIx64 "data 0x%" + PRIx64 "index mode wrong command 0x%x\n", + __func__, offset, data, reg_idx_command); + + switch (reg_idx_type) { + case gpio_reg_idx_data: + reg_value = set->data_read; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, DATA_VALUE)); + reg_value &= props->output; + reg_value = update_value_control_source(set, set->data_value, + reg_value); + set->data_read = reg_value; + aspeed_gpio_update(s, set, reg_value); + return; + case gpio_reg_idx_direction: + reg_value = set->direction; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, DIRECTION)); + /* + * where data is the value attempted to be written to the pin: + * pin type | input mask | output mask | expected value + * ------------------------------------------------------------ + * bidirectional | 1 | 1 | data + * input only | 1 | 0 | 0 + * output only | 0 | 1 | 1 + * no pin | 0 | 0 | 0 + * + * which is captured by: + * data = ( data | ~input) & output; + */ + reg_value = (reg_value | ~props->input) & props->output; + set->direction = update_value_control_source(set, set->direction, + reg_value); + break; + case gpio_reg_idx_interrupt: + reg_value = set->int_enable; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, INT_ENABLE)); + set->int_enable = update_value_control_source(set, set->int_enable, + reg_value); + reg_value = set->int_sens_0; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, INT_SENS_0)); + set->int_sens_0 = update_value_control_source(set, set->int_sens_0, + reg_value); + reg_value = set->int_sens_1; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, INT_SENS_1)); + set->int_sens_1 = update_value_control_source(set, set->int_sens_1, + reg_value); + reg_value = set->int_sens_2; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, INT_SENS_2)); + set->int_sens_2 = update_value_control_source(set, set->int_sens_2, + reg_value); + /* set interrupt status */ + reg_value = set->int_status; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, INT_STATUS)); + cleared = ctpop32(reg_value & set->int_status); + if (s->pending && cleared) { + assert(s->pending >= cleared); + s->pending -= cleared; + } + set->int_status &= ~reg_value; + break; + case gpio_reg_idx_debounce: + reg_value = set->debounce_1; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, DEBOUNCE_1)); + set->debounce_1 = update_value_control_source(set, set->debounce_1, + reg_value); + reg_value = set->debounce_2; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, DEBOUNCE_2)); + set->debounce_2 = update_value_control_source(set, set->debounce_2, + reg_value); + return; + case gpio_reg_idx_tolerance: + reg_value = set->reset_tol; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, RESET_TOLERANT)); + set->reset_tol = update_value_control_source(set, set->reset_tol, + reg_value); + return; + case gpio_reg_idx_cmd_src: + reg_value = set->cmd_source_0; + reg_value = deposit32(reg_value, GPIOS_PER_GROUP * group_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, COMMAND_SRC_0)); + set->cmd_source_0 = reg_value & ASPEED_CMD_SRC_MASK; + reg_value = set->cmd_source_1; + reg_value = deposit32(reg_value, GPIOS_PER_GROUP * group_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, COMMAND_SRC_1)); + set->cmd_source_1 = reg_value & ASPEED_CMD_SRC_MASK; + return; + case gpio_reg_idx_input_mask: + reg_value = set->input_mask; + reg_value = deposit32(reg_value, pin_idx, 1, + FIELD_EX32(data, GPIO_INDEX_REG, INPUT_MASK)); + /* + * feeds into interrupt generation + * 0: read from data value reg will be updated + * 1: read from data value reg will not be updated + */ + set->input_mask = reg_value & props->input; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%" PRIx64 "data 0x%" + PRIx64 "index mode wrong type 0x%x\n", + __func__, offset, data, reg_idx_type); + return; + } + aspeed_gpio_update(s, set, set->data_value); + return; +} + static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, uint32_t size) { @@ -610,6 +771,13 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, trace_aspeed_gpio_write(offset, data); idx = offset >> 2; + + /* check gpio index mode */ + if (idx == R_GPIO_INDEX_REG) { + aspeed_gpio_write_index_mode(opaque, offset, data, size); + return; + } + if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) { idx -= GPIO_DEBOUNCE_TIME_1; s->debounce_regs[idx] = (uint32_t) data; diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h index 6dee3cd438..41b36524d0 100644 --- a/include/hw/gpio/aspeed_gpio.h +++ b/include/hw/gpio/aspeed_gpio.h @@ -50,6 +50,20 @@ enum GPIORegType { gpio_reg_input_mask, }; +/* GPIO index mode */ +enum GPIORegIndexType { + gpio_reg_idx_data = 0, + gpio_reg_idx_direction, + gpio_reg_idx_interrupt, + gpio_reg_idx_debounce, + gpio_reg_idx_tolerance, + gpio_reg_idx_cmd_src, + gpio_reg_idx_input_mask, + gpio_reg_idx_reserved, + gpio_reg_idx_new_w_cmd_src, + gpio_reg_idx_new_r_cmd_src, +}; + typedef struct AspeedGPIOReg { uint16_t set_idx; enum GPIORegType type; From 554c294514dc7445c5442266a50012ed774d63fe Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Wed, 25 May 2022 10:31:33 +0200 Subject: [PATCH 14/15] hw/gpio: replace HWADDR_PRIx with PRIx64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. replace HWADDR_PRIx with PRIx64 2. fix indent issue Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Message-Id: <20220525053444.27228-5-jamin_lin@aspeedtech.com> Signed-off-by: Cédric Le Goater --- hw/gpio/aspeed_gpio.c | 8 ++++---- include/hw/gpio/aspeed_gpio.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index c834bf19f5..a62a673857 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -561,7 +561,7 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size) reg = &agc->reg_table[idx]; if (reg->set_idx >= agc->nr_gpio_sets) { qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%" - HWADDR_PRIx"\n", __func__, offset); + PRIx64"\n", __func__, offset); return 0; } @@ -611,7 +611,7 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size) break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%" - HWADDR_PRIx"\n", __func__, offset); + PRIx64"\n", __func__, offset); return 0; } @@ -787,7 +787,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, reg = &agc->reg_table[idx]; if (reg->set_idx >= agc->nr_gpio_sets) { qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%" - HWADDR_PRIx"\n", __func__, offset); + PRIx64"\n", __func__, offset); return; } @@ -872,7 +872,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%" - HWADDR_PRIx"\n", __func__, offset); + PRIx64"\n", __func__, offset); return; } aspeed_gpio_update(s, set, set->data_value); diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h index 41b36524d0..904eecf62c 100644 --- a/include/hw/gpio/aspeed_gpio.h +++ b/include/hw/gpio/aspeed_gpio.h @@ -67,7 +67,7 @@ enum GPIORegIndexType { typedef struct AspeedGPIOReg { uint16_t set_idx; enum GPIORegType type; - } AspeedGPIOReg; +} AspeedGPIOReg; struct AspeedGPIOClass { SysBusDevice parent_obj; From 52bcd997800fab67d57bea6d93e368f6f7a93b24 Mon Sep 17 00:00:00 2001 From: Howard Chiu Date: Wed, 25 May 2022 10:00:01 +0000 Subject: [PATCH 15/15] hw/arm/aspeed: Add i2c devices for AST2600 EVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add EEPROM and LM75 temperature sensor according to hardware schematic Signed-off-by: Howard Chiu Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 725c169488..98dc185acd 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -527,8 +527,15 @@ static void ast2500_evb_i2c_init(AspeedMachineState *bmc) static void ast2600_evb_i2c_init(AspeedMachineState *bmc) { - /* Start with some devices on our I2C busses */ - ast2500_evb_i2c_init(bmc); + AspeedSoCState *soc = &bmc->soc; + uint8_t *eeprom_buf = g_malloc0(8 * 1024); + + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 7), 0x50, + eeprom_buf); + + /* LM75 is compatible with TMP105 driver */ + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), + TYPE_TMP105, 0x4d); } static void romulus_bmc_i2c_init(AspeedMachineState *bmc)