aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-03-10 13:40:35 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2025-03-10 13:40:35 +0800
commit2e14ac3c9ca25c974bb300c45c5b0303862c177d (patch)
tree19e7f8f5107d9301063d20927ba613fe54acb30c
parent1843a0c01d06049f517fea7e155e5236e7287276 (diff)
parent5ab179db11ca297c9e89a6d57f954d31965cbd7b (diff)
downloadqemu-2e14ac3c9ca25c974bb300c45c5b0303862c177d.zip
qemu-2e14ac3c9ca25c974bb300c45c5b0303862c177d.tar.gz
qemu-2e14ac3c9ca25c974bb300c45c5b0303862c177d.tar.bz2
Merge tag 'pull-aspeed-20250309' of https://github.com/legoater/qemu into staging
aspeed queue: * Updated Aspeed OpenBMC functional test images * Introduced functional tests for witherspoon and bletchley machines * Added support for Non-maskable Interrupt on AST2700 SoC * Fixed HW strapping on AST2700 SoC * Added AST2700 HACE support * Added AST2700 A1 SoC support * Intoduced new ast2700a1-evb machine # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmfNnIUACgkQUaNDx8/7 # 7KFMGQ//YHvJV30PkI9CHO6Gbk3CmWftI9Dbjn7goghV/hArVThiq9fve3n2GxYJ # aKrpQZ3BK5SOvcp1zzSc2HrCxmzhy98TZfH2vqwqx3T7uqLDTGgo6xGRYT7+fuVn # SzQaxFJ5hG8LdR4GqDcuUlUVyjVM3ZGR8E/Guj6s6Um1gctZsjy7Z+CdAWDlXFWM # uJoI9EwbhdIWYWF6jJw3myOjMhXHNZs0IobvS7yzZ3DGX0o/P3jRxFYeS6P9lQDl # +TmZ/IRuZDMgA3N+jAyQfMjmlvtA0BygLUbrKTJXb6Bz0BhUjUVahOv6Mnq86yZh # glKCg9LB4BVZneTw5VSd3Tj6Lt/qNhhJjRlV+UYxWzZ0zmFNdkq08RRxKCmMbtYi # t4DsT7xGqfMK9JXEOIWa5REyP4i5llzKe173ml4wSi1Nro9hzZz5cgAKS+7Eabni # nCLhOi26hwkBUCqCKN2eTyRKqOtyftOiKGYog1EV4YtwbnfQS072h0FJz8H6Ibkt # n+twrO8NY31Y0JMzj0GksZ0JSlV/04mtuIpNMSqPizMN/VZPznqwCiaGADtips4f # DoJRtJyDaI/n0IlbtcRpcsrax0uQQEdClvFlcfOkSvkm1aZU2q7wwSKbyOkcnWgd # qnxkUqjHnQTlUSEOqjhtEcw7Bv6J7Mn5IwN0zKROIZp9ia+LZwI= # =O5Kv # -----END PGP SIGNATURE----- # gpg: Signature made Sun 09 Mar 2025 21:49:57 HKT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [full] # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-aspeed-20250309' of https://github.com/legoater/qemu: (46 commits) docs/specs: Add aspeed-intc tests/functional/aspeed: Add test case for AST2700 A1 tests/functional/aspeed: Update test ASPEED SDK v09.05 tests/functional/aspeed: Update temperature hwmon path tests/functional/aspeed: Introduce start_ast2700_test API hw/arm/aspeed_ast27x0: Sort the memmap table by mapping address hw/arm/aspeed: Add Machine Support for AST2700 A1 hw/arm/aspeed_ast27x0: Add SoC Support for AST2700 A1 hw/arm/aspeed_ast27x0: Support two levels of INTC controllers for AST2700 A1 hw/arm/aspeed_ast27x0: Define an Array of AspeedINTCState with Two Instances hw/arm/aspeed_ast27x0.c Support AST2700 A1 GIC Interrupt Mapping hw/misc/aspeed_scu: Add Support for AST2700/AST2750 A1 Silicon Revisions hw/intc/aspeed: Add Support for AST2700 INTCIO Controller hw/intc/aspeed: Add Support for Multi-Output IRQ Handling hw/intc/aspeed: Introduce IRQ handler function to reduce code duplication hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq index and register address hw/intc/aspeed: Refactor INTC to support separate input and output pin indices hw/intc/aspeed: Add support for multiple output pins in INTC hw/intc/aspeed: Rename num_ints to num_inpins for clarity hw/intc/aspeed: Support different memory region ops ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r--docs/specs/aspeed-intc.rst136
-rw-r--r--docs/specs/index.rst1
-rw-r--r--hw/arm/aspeed.c39
-rw-r--r--hw/arm/aspeed_ast10x0.c3
-rw-r--r--hw/arm/aspeed_ast2400.c4
-rw-r--r--hw/arm/aspeed_ast2600.c3
-rw-r--r--hw/arm/aspeed_ast27x0.c359
-rw-r--r--hw/intc/aspeed_intc.c667
-rw-r--r--hw/intc/trace-events25
-rw-r--r--hw/misc/aspeed_hace.c55
-rw-r--r--hw/misc/aspeed_scu.c10
-rw-r--r--include/hw/arm/aspeed_soc.h4
-rw-r--r--include/hw/intc/aspeed_intc.h36
-rw-r--r--include/hw/misc/aspeed_hace.h2
-rw-r--r--include/hw/misc/aspeed_scu.h2
-rw-r--r--tests/functional/aspeed.py24
-rw-r--r--tests/functional/meson.build4
-rwxr-xr-xtests/functional/test_aarch64_aspeed.py47
-rw-r--r--tests/functional/test_arm_aspeed_bletchley.py25
-rwxr-xr-xtests/functional/test_arm_aspeed_palmetto.py13
-rwxr-xr-xtests/functional/test_arm_aspeed_romulus.py13
-rw-r--r--tests/functional/test_arm_aspeed_witherspoon.py25
22 files changed, 1150 insertions, 347 deletions
diff --git a/docs/specs/aspeed-intc.rst b/docs/specs/aspeed-intc.rst
new file mode 100644
index 0000000..9cefd7f
--- /dev/null
+++ b/docs/specs/aspeed-intc.rst
@@ -0,0 +1,136 @@
+===========================
+ASPEED Interrupt Controller
+===========================
+
+AST2700
+-------
+There are a total of 480 interrupt sources in AST2700. Due to the limitation of
+interrupt numbers of processors, the interrupts are merged every 32 sources for
+interrupt numbers greater than 127.
+
+There are two levels of interrupt controllers, INTC (CPU Die) and INTCIO
+(I/O Die).
+
+Interrupt Mapping
+-----------------
+- INTC: Handles interrupt sources 0 - 127 and integrates signals from INTCIO.
+- INTCIO: Handles interrupt sources 128 - 319 independently.
+
+QEMU Support
+------------
+Currently, only GIC 192 to 201 are supported, and their source interrupts are
+from INTCIO and connected to INTC at input pin 0 and output pins 0 to 9 for
+GIC 192-201.
+
+Design for GICINT 196
+---------------------
+The orgate has interrupt sources ranging from 0 to 31, with its output pin
+connected to INTCIO "T0 GICINT_196". The output pin is then connected to INTC
+"GIC_192_201" at bit 4, and its bit 4 output pin is connected to GIC 196.
+
+INTC GIC_192_201 Output Pin Mapping
+-----------------------------------
+The design of INTC GIC_192_201 have 10 output pins, mapped as following:
+
+==== ====
+Bit GIC
+==== ====
+0 192
+1 193
+2 194
+3 195
+4 196
+5 197
+6 198
+7 199
+8 200
+9 201
+==== ====
+
+AST2700 A0
+----------
+It has only one INTC controller, and currently, only GIC 128-136 is supported.
+To support both AST2700 A1 and AST2700 A0, there are 10 OR gates in the INTC,
+with gates 1 to 9 supporting GIC 128-136.
+
+Design for GICINT 132
+---------------------
+The orgate has interrupt sources ranging from 0 to 31, with its output pin
+connected to INTC. The output pin is then connected to GIC 132.
+
+Block Diagram of GICINT 196 for AST2700 A1 and GICINT 132 for AST2700 A0
+------------------------------------------------------------------------
+
+.. code-block::
+
+ |-------------------------------------------------------------------------------------------------------|
+ | AST2700 A1 Design |
+ | To GICINT196 |
+ | |
+ | ETH1 |-----------| |--------------------------| |--------------| |
+ | -------->|0 | | INTCIO | | orgates[0] | |
+ | ETH2 | 4| orgates[0]------>|inpin[0]-------->outpin[0]|------->| 0 | |
+ | -------->|1 5| orgates[1]------>|inpin[1]-------->outpin[1]|------->| 1 | |
+ | ETH3 | 6| orgates[2]------>|inpin[2]-------->outpin[2]|------->| 2 | |
+ | -------->|2 19| orgates[3]------>|inpin[3]-------->outpin[3]|------->| 3 OR[0:9] |-----| |
+ | UART0 | 20|-->orgates[4]------>|inpin[4]-------->outpin[4]|------->| 4 | | |
+ | -------->|7 21| orgates[5]------>|inpin[5]-------->outpin[5]|------->| 5 | | |
+ | UART1 | 22| orgates[6]------>|inpin[6]-------->outpin[6]|------->| 6 | | |
+ | -------->|8 23| orgates[7]------>|inpin[7]-------->outpin[7]|------->| 7 | | |
+ | UART2 | 24| orgates[8]------>|inpin[8]-------->outpin[8]|------->| 8 | | |
+ | -------->|9 25| orgates[9]------>|inpin[9]-------->outpin[9]|------->| 9 | | |
+ | UART3 | 26| |--------------------------| |--------------| | |
+ | ---------|10 27| | |
+ | UART5 | 28| | |
+ | -------->|11 29| | |
+ | UART6 | | | |
+ | -------->|12 30| |-----------------------------------------------------------------------| |
+ | UART7 | 31| | |
+ | -------->|13 | | |
+ | UART8 | OR[0:31] | | |------------------------------| |----------| |
+ | -------->|14 | | | INTC | | GIC | |
+ | UART9 | | | |inpin[0:0]--------->outpin[0] |---------->|192 | |
+ | -------->|15 | | |inpin[0:1]--------->outpin[1] |---------->|193 | |
+ | UART10 | | | |inpin[0:2]--------->outpin[2] |---------->|194 | |
+ | -------->|16 | | |inpin[0:3]--------->outpin[3] |---------->|195 | |
+ | UART11 | | |--------------> |inpin[0:4]--------->outpin[4] |---------->|196 | |
+ | -------->|17 | |inpin[0:5]--------->outpin[5] |---------->|197 | |
+ | UART12 | | |inpin[0:6]--------->outpin[6] |---------->|198 | |
+ | -------->|18 | |inpin[0:7]--------->outpin[7] |---------->|199 | |
+ | |-----------| |inpin[0:8]--------->outpin[8] |---------->|200 | |
+ | |inpin[0:9]--------->outpin[9] |---------->|201 | |
+ |-------------------------------------------------------------------------------------------------------|
+ |-------------------------------------------------------------------------------------------------------|
+ | ETH1 |-----------| orgates[1]------->|inpin[1]----------->outpin[10]|---------->|128 | |
+ | -------->|0 | orgates[2]------->|inpin[2]----------->outpin[11]|---------->|129 | |
+ | ETH2 | 4| orgates[3]------->|inpin[3]----------->outpin[12]|---------->|130 | |
+ | -------->|1 5| orgates[4]------->|inpin[4]----------->outpin[13]|---------->|131 | |
+ | ETH3 | 6|---->orgates[5]------->|inpin[5]----------->outpin[14]|---------->|132 | |
+ | -------->|2 19| orgates[6]------->|inpin[6]----------->outpin[15]|---------->|133 | |
+ | UART0 | 20| orgates[7]------->|inpin[7]----------->outpin[16]|---------->|134 | |
+ | -------->|7 21| orgates[8]------->|inpin[8]----------->outpin[17]|---------->|135 | |
+ | UART1 | 22| orgates[9]------->|inpin[9]----------->outpin[18]|---------->|136 | |
+ | -------->|8 23| |------------------------------| |----------| |
+ | UART2 | 24| |
+ | -------->|9 25| AST2700 A0 Design |
+ | UART3 | 26| |
+ | -------->|10 27| |
+ | UART5 | 28| |
+ | -------->|11 29| GICINT132 |
+ | UART6 | | |
+ | -------->|12 30| |
+ | UART7 | 31| |
+ | -------->|13 | |
+ | UART8 | OR[0:31] | |
+ | -------->|14 | |
+ | UART9 | | |
+ | -------->|15 | |
+ | UART10 | | |
+ | -------->|16 | |
+ | UART11 | | |
+ | -------->|17 | |
+ | UART12 | | |
+ | -------->|18 | |
+ | |-----------| |
+ | |
+ |-------------------------------------------------------------------------------------------------------|
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index d7675ce..f19d73c 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -38,3 +38,4 @@ guest hardware that is specific to QEMU.
rocker
riscv-iommu
riscv-aia
+ aspeed-intc
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 98bf071..82f4258 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -181,8 +181,10 @@ struct AspeedMachineState {
#ifdef TARGET_AARCH64
/* AST2700 evb hardware value */
-#define AST2700_EVB_HW_STRAP1 0x000000C0
-#define AST2700_EVB_HW_STRAP2 0x00000003
+/* SCU HW Strap1 */
+#define AST2700_EVB_HW_STRAP1 0x00000800
+/* SCUIO HW Strap1 */
+#define AST2700_EVB_HW_STRAP2 0x00000700
#endif
/* Rainier hardware value: (QEMU prototype) */
@@ -1671,12 +1673,13 @@ static void ast2700_evb_i2c_init(AspeedMachineState *bmc)
TYPE_TMP105, 0x4d);
}
-static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
+static void aspeed_machine_ast2700a0_evb_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
- mc->desc = "Aspeed AST2700 EVB (Cortex-A35)";
+ mc->alias = "ast2700-evb";
+ mc->desc = "Aspeed AST2700 A0 EVB (Cortex-A35)";
amc->soc_name = "ast2700-a0";
amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
@@ -1690,6 +1693,26 @@ static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
}
+
+static void aspeed_machine_ast2700a1_evb_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+ mc->desc = "Aspeed AST2700 A1 EVB (Cortex-A35)";
+ amc->soc_name = "ast2700-a1";
+ amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
+ amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
+ amc->fmc_model = "w25q01jvq";
+ amc->spi_model = "w25q512jv";
+ amc->num_cs = 2;
+ amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON;
+ amc->uart_default = ASPEED_DEV_UART12;
+ amc->i2c_init = ast2700_evb_i2c_init;
+ mc->auto_create_sdcard = true;
+ mc->default_ram_size = 1 * GiB;
+ aspeed_machine_class_init_cpus_defaults(mc);
+}
#endif
static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
@@ -1815,9 +1838,13 @@ static const TypeInfo aspeed_machine_types[] = {
.class_init = aspeed_minibmc_machine_ast1030_evb_class_init,
#ifdef TARGET_AARCH64
}, {
- .name = MACHINE_TYPE_NAME("ast2700-evb"),
+ .name = MACHINE_TYPE_NAME("ast2700a0-evb"),
+ .parent = TYPE_ASPEED_MACHINE,
+ .class_init = aspeed_machine_ast2700a0_evb_class_init,
+ }, {
+ .name = MACHINE_TYPE_NAME("ast2700a1-evb"),
.parent = TYPE_ASPEED_MACHINE,
- .class_init = aspeed_machine_ast2700_evb_class_init,
+ .class_init = aspeed_machine_ast2700a1_evb_class_init,
#endif
}, {
.name = TYPE_ASPEED_MACHINE,
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index e76c710..ec329f4 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -116,7 +116,7 @@ static void aspeed_soc_ast1030_init(Object *obj)
char typename[64];
int i;
- if (sscanf(sc->name, "%7s", socname) != 1) {
+ if (sscanf(object_get_typename(obj), "%7s", socname) != 1) {
g_assert_not_reached();
}
@@ -428,7 +428,6 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data)
dc->user_creatable = false;
dc->realize = aspeed_soc_ast1030_realize;
- sc->name = "ast1030-a1";
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST1030_A1_SILICON_REV;
sc->sram_size = 0xc0000;
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 8784b6e..0158f6e 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -151,7 +151,7 @@ static void aspeed_ast2400_soc_init(Object *obj)
char socname[8];
char typename[64];
- if (sscanf(sc->name, "%7s", socname) != 1) {
+ if (sscanf(object_get_typename(obj), "%7s", socname) != 1) {
g_assert_not_reached();
}
@@ -515,7 +515,6 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data)
/* Reason: Uses serial_hds and nd_table in realize() directly */
dc->user_creatable = false;
- sc->name = "ast2400-a1";
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2400_A1_SILICON_REV;
sc->sram_size = 0x8000;
@@ -544,7 +543,6 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data)
/* Reason: Uses serial_hds and nd_table in realize() directly */
dc->user_creatable = false;
- sc->name = "ast2500-a1";
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2500_A1_SILICON_REV;
sc->sram_size = 0x9000;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 0721048..1f994ba 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -157,7 +157,7 @@ static void aspeed_soc_ast2600_init(Object *obj)
char socname[8];
char typename[64];
- if (sscanf(sc->name, "%7s", socname) != 1) {
+ if (sscanf(object_get_typename(obj), "%7s", socname) != 1) {
g_assert_not_reached();
}
@@ -666,7 +666,6 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
/* Reason: The Aspeed SoC can only be instantiated from a board */
dc->user_creatable = false;
- sc->name = "ast2600-a3";
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2600_A3_SILICON_REV;
sc->sram_size = 0x16400;
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 2d0c99f..dce7255 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -24,16 +24,40 @@
#include "qemu/log.h"
static const hwaddr aspeed_soc_ast2700_memmap[] = {
- [ASPEED_DEV_SPI_BOOT] = 0x400000000,
[ASPEED_DEV_SRAM] = 0x10000000,
+ [ASPEED_DEV_HACE] = 0x12070000,
+ [ASPEED_DEV_EMMC] = 0x12090000,
+ [ASPEED_DEV_INTC] = 0x12100000,
+ [ASPEED_GIC_DIST] = 0x12200000,
+ [ASPEED_GIC_REDIST] = 0x12280000,
[ASPEED_DEV_SDMC] = 0x12C00000,
[ASPEED_DEV_SCU] = 0x12C02000,
+ [ASPEED_DEV_RTC] = 0x12C0F000,
+ [ASPEED_DEV_TIMER1] = 0x12C10000,
+ [ASPEED_DEV_SLI] = 0x12C17000,
+ [ASPEED_DEV_UART4] = 0X12C1A000,
+ [ASPEED_DEV_FMC] = 0x14000000,
+ [ASPEED_DEV_SPI0] = 0x14010000,
+ [ASPEED_DEV_SPI1] = 0x14020000,
+ [ASPEED_DEV_SPI2] = 0x14030000,
+ [ASPEED_DEV_MII1] = 0x14040000,
+ [ASPEED_DEV_MII2] = 0x14040008,
+ [ASPEED_DEV_MII3] = 0x14040010,
+ [ASPEED_DEV_ETH1] = 0x14050000,
+ [ASPEED_DEV_ETH2] = 0x14060000,
+ [ASPEED_DEV_ETH3] = 0x14070000,
+ [ASPEED_DEV_SDHCI] = 0x14080000,
+ [ASPEED_DEV_ADC] = 0x14C00000,
[ASPEED_DEV_SCUIO] = 0x14C02000,
+ [ASPEED_DEV_GPIO] = 0x14C0B000,
+ [ASPEED_DEV_I2C] = 0x14C0F000,
+ [ASPEED_DEV_INTCIO] = 0x14C18000,
+ [ASPEED_DEV_SLIIO] = 0x14C1E000,
+ [ASPEED_DEV_VUART] = 0X14C30000,
[ASPEED_DEV_UART0] = 0X14C33000,
[ASPEED_DEV_UART1] = 0X14C33100,
[ASPEED_DEV_UART2] = 0X14C33200,
[ASPEED_DEV_UART3] = 0X14C33300,
- [ASPEED_DEV_UART4] = 0X12C1A000,
[ASPEED_DEV_UART5] = 0X14C33400,
[ASPEED_DEV_UART6] = 0X14C33500,
[ASPEED_DEV_UART7] = 0X14C33600,
@@ -43,41 +67,44 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
[ASPEED_DEV_UART11] = 0X14C33A00,
[ASPEED_DEV_UART12] = 0X14C33B00,
[ASPEED_DEV_WDT] = 0x14C37000,
- [ASPEED_DEV_VUART] = 0X14C30000,
- [ASPEED_DEV_FMC] = 0x14000000,
- [ASPEED_DEV_SPI0] = 0x14010000,
- [ASPEED_DEV_SPI1] = 0x14020000,
- [ASPEED_DEV_SPI2] = 0x14030000,
+ [ASPEED_DEV_SPI_BOOT] = 0x100000000,
[ASPEED_DEV_SDRAM] = 0x400000000,
- [ASPEED_DEV_MII1] = 0x14040000,
- [ASPEED_DEV_MII2] = 0x14040008,
- [ASPEED_DEV_MII3] = 0x14040010,
- [ASPEED_DEV_ETH1] = 0x14050000,
- [ASPEED_DEV_ETH2] = 0x14060000,
- [ASPEED_DEV_ETH3] = 0x14070000,
- [ASPEED_DEV_EMMC] = 0x12090000,
- [ASPEED_DEV_INTC] = 0x12100000,
- [ASPEED_DEV_SLI] = 0x12C17000,
- [ASPEED_DEV_SLIIO] = 0x14C1E000,
- [ASPEED_GIC_DIST] = 0x12200000,
- [ASPEED_GIC_REDIST] = 0x12280000,
- [ASPEED_DEV_ADC] = 0x14C00000,
- [ASPEED_DEV_I2C] = 0x14C0F000,
- [ASPEED_DEV_GPIO] = 0x14C0B000,
- [ASPEED_DEV_RTC] = 0x12C0F000,
- [ASPEED_DEV_SDHCI] = 0x14080000,
- [ASPEED_DEV_TIMER1] = 0x12C10000,
};
#define AST2700_MAX_IRQ 256
/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
-static const int aspeed_soc_ast2700_irqmap[] = {
+static const int aspeed_soc_ast2700a0_irqmap[] = {
+ [ASPEED_DEV_SDMC] = 0,
+ [ASPEED_DEV_HACE] = 4,
+ [ASPEED_DEV_XDMA] = 5,
+ [ASPEED_DEV_UART4] = 8,
+ [ASPEED_DEV_SCU] = 12,
+ [ASPEED_DEV_RTC] = 13,
+ [ASPEED_DEV_EMMC] = 15,
+ [ASPEED_DEV_TIMER1] = 16,
+ [ASPEED_DEV_TIMER2] = 17,
+ [ASPEED_DEV_TIMER3] = 18,
+ [ASPEED_DEV_TIMER4] = 19,
+ [ASPEED_DEV_TIMER5] = 20,
+ [ASPEED_DEV_TIMER6] = 21,
+ [ASPEED_DEV_TIMER7] = 22,
+ [ASPEED_DEV_TIMER8] = 23,
+ [ASPEED_DEV_DP] = 28,
+ [ASPEED_DEV_LPC] = 128,
+ [ASPEED_DEV_IBT] = 128,
+ [ASPEED_DEV_KCS] = 128,
+ [ASPEED_DEV_ADC] = 130,
+ [ASPEED_DEV_GPIO] = 130,
+ [ASPEED_DEV_I2C] = 130,
+ [ASPEED_DEV_FMC] = 131,
+ [ASPEED_DEV_WDT] = 131,
+ [ASPEED_DEV_PWM] = 131,
+ [ASPEED_DEV_I3C] = 131,
[ASPEED_DEV_UART0] = 132,
[ASPEED_DEV_UART1] = 132,
[ASPEED_DEV_UART2] = 132,
[ASPEED_DEV_UART3] = 132,
- [ASPEED_DEV_UART4] = 8,
[ASPEED_DEV_UART5] = 132,
[ASPEED_DEV_UART6] = 132,
[ASPEED_DEV_UART7] = 132,
@@ -86,14 +113,21 @@ static const int aspeed_soc_ast2700_irqmap[] = {
[ASPEED_DEV_UART10] = 132,
[ASPEED_DEV_UART11] = 132,
[ASPEED_DEV_UART12] = 132,
- [ASPEED_DEV_FMC] = 131,
+ [ASPEED_DEV_ETH1] = 132,
+ [ASPEED_DEV_ETH2] = 132,
+ [ASPEED_DEV_ETH3] = 132,
+ [ASPEED_DEV_PECI] = 133,
+ [ASPEED_DEV_SDHCI] = 133,
+};
+
+static const int aspeed_soc_ast2700a1_irqmap[] = {
[ASPEED_DEV_SDMC] = 0,
- [ASPEED_DEV_SCU] = 12,
- [ASPEED_DEV_ADC] = 130,
+ [ASPEED_DEV_HACE] = 4,
[ASPEED_DEV_XDMA] = 5,
- [ASPEED_DEV_EMMC] = 15,
- [ASPEED_DEV_GPIO] = 130,
+ [ASPEED_DEV_UART4] = 8,
+ [ASPEED_DEV_SCU] = 12,
[ASPEED_DEV_RTC] = 13,
+ [ASPEED_DEV_EMMC] = 15,
[ASPEED_DEV_TIMER1] = 16,
[ASPEED_DEV_TIMER2] = 17,
[ASPEED_DEV_TIMER3] = 18,
@@ -102,38 +136,58 @@ static const int aspeed_soc_ast2700_irqmap[] = {
[ASPEED_DEV_TIMER6] = 21,
[ASPEED_DEV_TIMER7] = 22,
[ASPEED_DEV_TIMER8] = 23,
- [ASPEED_DEV_WDT] = 131,
- [ASPEED_DEV_PWM] = 131,
- [ASPEED_DEV_LPC] = 128,
- [ASPEED_DEV_IBT] = 128,
- [ASPEED_DEV_I2C] = 130,
- [ASPEED_DEV_PECI] = 133,
- [ASPEED_DEV_ETH1] = 132,
- [ASPEED_DEV_ETH2] = 132,
- [ASPEED_DEV_ETH3] = 132,
- [ASPEED_DEV_HACE] = 4,
- [ASPEED_DEV_KCS] = 128,
[ASPEED_DEV_DP] = 28,
- [ASPEED_DEV_I3C] = 131,
- [ASPEED_DEV_SDHCI] = 133,
+ [ASPEED_DEV_LPC] = 192,
+ [ASPEED_DEV_IBT] = 192,
+ [ASPEED_DEV_KCS] = 192,
+ [ASPEED_DEV_I2C] = 194,
+ [ASPEED_DEV_ADC] = 194,
+ [ASPEED_DEV_GPIO] = 194,
+ [ASPEED_DEV_FMC] = 195,
+ [ASPEED_DEV_WDT] = 195,
+ [ASPEED_DEV_PWM] = 195,
+ [ASPEED_DEV_I3C] = 195,
+ [ASPEED_DEV_UART0] = 196,
+ [ASPEED_DEV_UART1] = 196,
+ [ASPEED_DEV_UART2] = 196,
+ [ASPEED_DEV_UART3] = 196,
+ [ASPEED_DEV_UART5] = 196,
+ [ASPEED_DEV_UART6] = 196,
+ [ASPEED_DEV_UART7] = 196,
+ [ASPEED_DEV_UART8] = 196,
+ [ASPEED_DEV_UART9] = 196,
+ [ASPEED_DEV_UART10] = 196,
+ [ASPEED_DEV_UART11] = 196,
+ [ASPEED_DEV_UART12] = 196,
+ [ASPEED_DEV_ETH1] = 196,
+ [ASPEED_DEV_ETH2] = 196,
+ [ASPEED_DEV_ETH3] = 196,
+ [ASPEED_DEV_PECI] = 197,
+ [ASPEED_DEV_SDHCI] = 197,
};
/* GICINT 128 */
-static const int aspeed_soc_ast2700_gic128_intcmap[] = {
+/* GICINT 192 */
+static const int ast2700_gic128_gic192_intcmap[] = {
[ASPEED_DEV_LPC] = 0,
[ASPEED_DEV_IBT] = 2,
[ASPEED_DEV_KCS] = 4,
};
+/* GICINT 129 */
+/* GICINT 193 */
+
/* GICINT 130 */
-static const int aspeed_soc_ast2700_gic130_intcmap[] = {
+/* GICINT 194 */
+static const int ast2700_gic130_gic194_intcmap[] = {
[ASPEED_DEV_I2C] = 0,
[ASPEED_DEV_ADC] = 16,
[ASPEED_DEV_GPIO] = 18,
};
/* GICINT 131 */
-static const int aspeed_soc_ast2700_gic131_intcmap[] = {
+/* GICINT 195 */
+static const int ast2700_gic131_gic195_intcmap[] = {
[ASPEED_DEV_I3C] = 0,
[ASPEED_DEV_WDT] = 16,
[ASPEED_DEV_FMC] = 25,
@@ -141,7 +195,8 @@ static const int aspeed_soc_ast2700_gic131_intcmap[] = {
};
/* GICINT 132 */
-static const int aspeed_soc_ast2700_gic132_intcmap[] = {
+/* GICINT 196 */
+static const int ast2700_gic132_gic196_intcmap[] = {
[ASPEED_DEV_ETH1] = 0,
[ASPEED_DEV_ETH2] = 1,
[ASPEED_DEV_ETH3] = 2,
@@ -160,40 +215,58 @@ static const int aspeed_soc_ast2700_gic132_intcmap[] = {
};
/* GICINT 133 */
-static const int aspeed_soc_ast2700_gic133_intcmap[] = {
+/* GICINT 197 */
+static const int ast2700_gic133_gic197_intcmap[] = {
[ASPEED_DEV_SDHCI] = 1,
[ASPEED_DEV_PECI] = 4,
};
/* GICINT 128 ~ 136 */
+/* GICINT 192 ~ 201 */
struct gic_intc_irq_info {
int irq;
+ int intc_idx;
+ int orgate_idx;
const int *ptr;
};
-static const struct gic_intc_irq_info aspeed_soc_ast2700_gic_intcmap[] = {
- {128, aspeed_soc_ast2700_gic128_intcmap},
- {129, NULL},
- {130, aspeed_soc_ast2700_gic130_intcmap},
- {131, aspeed_soc_ast2700_gic131_intcmap},
- {132, aspeed_soc_ast2700_gic132_intcmap},
- {133, aspeed_soc_ast2700_gic133_intcmap},
- {134, NULL},
- {135, NULL},
- {136, NULL},
+static const struct gic_intc_irq_info ast2700_gic_intcmap[] = {
+ {192, 1, 0, ast2700_gic128_gic192_intcmap},
+ {193, 1, 1, NULL},
+ {194, 1, 2, ast2700_gic130_gic194_intcmap},
+ {195, 1, 3, ast2700_gic131_gic195_intcmap},
+ {196, 1, 4, ast2700_gic132_gic196_intcmap},
+ {197, 1, 5, ast2700_gic133_gic197_intcmap},
+ {198, 1, 6, NULL},
+ {199, 1, 7, NULL},
+ {200, 1, 8, NULL},
+ {201, 1, 9, NULL},
+ {128, 0, 1, ast2700_gic128_gic192_intcmap},
+ {129, 0, 2, NULL},
+ {130, 0, 3, ast2700_gic130_gic194_intcmap},
+ {131, 0, 4, ast2700_gic131_gic195_intcmap},
+ {132, 0, 5, ast2700_gic132_gic196_intcmap},
+ {133, 0, 6, ast2700_gic133_gic197_intcmap},
+ {134, 0, 7, NULL},
+ {135, 0, 8, NULL},
+ {136, 0, 9, NULL},
};
static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
{
Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ int or_idx;
+ int idx;
int i;
- for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
- if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
- assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
- return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
- aspeed_soc_ast2700_gic_intcmap[i].ptr[dev]);
+ for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
+ if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
+ assert(ast2700_gic_intcmap[i].ptr);
+ or_idx = ast2700_gic_intcmap[i].orgate_idx;
+ idx = ast2700_gic_intcmap[i].intc_idx;
+ return qdev_get_gpio_in(DEVICE(&a->intc[idx].orgates[or_idx]),
+ ast2700_gic_intcmap[i].ptr[dev]);
}
}
@@ -205,18 +278,23 @@ static qemu_irq aspeed_soc_ast2700_get_irq_index(AspeedSoCState *s, int dev,
{
Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ int or_idx;
+ int idx;
int i;
- for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
- if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
- assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
- return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
- aspeed_soc_ast2700_gic_intcmap[i].ptr[dev] + index);
+ for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
+ if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
+ assert(ast2700_gic_intcmap[i].ptr);
+ or_idx = ast2700_gic_intcmap[i].orgate_idx;
+ idx = ast2700_gic_intcmap[i].intc_idx;
+ return qdev_get_gpio_in(DEVICE(&a->intc[idx].orgates[or_idx]),
+ ast2700_gic_intcmap[i].ptr[dev] + index);
}
}
/*
- * Invalid orgate index, device irq should be 128 to 136.
+ * Invalid OR gate index, device IRQ should be between 128 to 136
+ * and 192 to 201.
*/
g_assert_not_reached();
}
@@ -316,7 +394,7 @@ static void aspeed_soc_ast2700_init(Object *obj)
char socname[8];
char typename[64];
- if (sscanf(sc->name, "%7s", socname) != 1) {
+ if (sscanf(object_get_typename(obj), "%7s", socname) != 1) {
g_assert_not_reached();
}
@@ -332,14 +410,21 @@ static void aspeed_soc_ast2700_init(Object *obj)
sc->silicon_rev);
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
"hw-strap1");
- object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
- "hw-strap2");
object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu),
"hw-prot-key");
object_initialize_child(obj, "scuio", &s->scuio, TYPE_ASPEED_2700_SCUIO);
qdev_prop_set_uint32(DEVICE(&s->scuio), "silicon-rev",
sc->silicon_rev);
+ /*
+ * There is one hw-strap1 register in the SCU (CPU DIE) and another
+ * hw-strap1 register in the SCUIO (IO DIE). To reuse the current design
+ * of hw-strap, hw-strap1 is assigned to the SCU and sets the value in the
+ * SCU hw-strap1 register, while hw-strap2 is assigned to the SCUIO and
+ * sets the value in the SCUIO hw-strap1 register.
+ */
+ object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scuio),
+ "hw-strap1");
snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
object_initialize_child(obj, "fmc", &s->fmc, typename);
@@ -372,7 +457,9 @@ static void aspeed_soc_ast2700_init(Object *obj)
object_initialize_child(obj, "sli", &s->sli, TYPE_ASPEED_2700_SLI);
object_initialize_child(obj, "sliio", &s->sliio, TYPE_ASPEED_2700_SLIIO);
- object_initialize_child(obj, "intc", &a->intc, TYPE_ASPEED_2700_INTC);
+ object_initialize_child(obj, "intc", &a->intc[0], TYPE_ASPEED_2700_INTC);
+ object_initialize_child(obj, "intcio", &a->intc[1],
+ TYPE_ASPEED_2700_INTCIO);
snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
object_initialize_child(obj, "adc", &s->adc, typename);
@@ -401,6 +488,9 @@ static void aspeed_soc_ast2700_init(Object *obj)
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
object_initialize_child(obj, "timerctrl", &s->timerctrl, typename);
+
+ snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname);
+ object_initialize_child(obj, "hace", &s->hace, typename);
}
/*
@@ -470,6 +560,10 @@ static bool aspeed_soc_ast2700_gic_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
sysbus_connect_irq(gicbusdev, i + 3 * sc->num_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+ sysbus_connect_irq(gicbusdev, i + 4 * sc->num_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_NMI));
+ sysbus_connect_irq(gicbusdev, i + 5 * sc->num_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VINMI));
}
return true;
@@ -481,7 +575,8 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
AspeedSoCState *s = ASPEED_SOC(dev);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
- AspeedINTCClass *ic = ASPEED_INTC_GET_CLASS(&a->intc);
+ AspeedINTCClass *ic = ASPEED_INTC_GET_CLASS(&a->intc[0]);
+ AspeedINTCClass *icio = ASPEED_INTC_GET_CLASS(&a->intc[1]);
g_autofree char *sram_name = NULL;
qemu_irq irq;
@@ -512,20 +607,45 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
}
/* INTC */
- if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc), errp)) {
+ if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0,
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[0]), 0,
sc->memmap[ASPEED_DEV_INTC]);
- /* GICINT orgates -> INTC -> GIC */
- for (i = 0; i < ic->num_ints; i++) {
- qdev_connect_gpio_out(DEVICE(&a->intc.orgates[i]), 0,
- qdev_get_gpio_in(DEVICE(&a->intc), i));
- sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), i,
+ /* INTCIO */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[1]), errp)) {
+ return;
+ }
+
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[1]), 0,
+ sc->memmap[ASPEED_DEV_INTCIO]);
+
+ /* irq sources -> orgates -> INTC */
+ for (i = 0; i < ic->num_inpins; i++) {
+ qdev_connect_gpio_out(DEVICE(&a->intc[0].orgates[i]), 0,
+ qdev_get_gpio_in(DEVICE(&a->intc[0]), i));
+ }
+
+ /* INTC -> GIC192 - GIC201 */
+ /* INTC -> GIC128 - GIC136 */
+ for (i = 0; i < ic->num_outpins; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc[0]), i,
qdev_get_gpio_in(DEVICE(&a->gic),
- aspeed_soc_ast2700_gic_intcmap[i].irq));
+ ast2700_gic_intcmap[i].irq));
+ }
+
+ /* irq source -> orgates -> INTCIO */
+ for (i = 0; i < icio->num_inpins; i++) {
+ qdev_connect_gpio_out(DEVICE(&a->intc[1].orgates[i]), 0,
+ qdev_get_gpio_in(DEVICE(&a->intc[1]), i));
+ }
+
+ /* INTCIO -> INTC */
+ for (i = 0; i < icio->num_outpins; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc[1]), i,
+ qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), i));
}
/* SRAM */
@@ -676,10 +796,22 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
/*
* The AST2700 I2C controller has one source INTC per bus.
- * I2C buses interrupt are connected to GICINT130_INTC
- * from bit 0 to bit 15.
- * I2C bus 0 is connected to GICINT130_INTC at bit 0.
- * I2C bus 15 is connected to GICINT130_INTC at bit 15.
+ *
+ * For AST2700 A0:
+ * I2C bus interrupts are connected to the OR gate from bit 0 to bit
+ * 15, and the OR gate output pin is connected to the input pin of
+ * GICINT130 of INTC (CPU Die). Then, the output pin is connected to
+ * the GIC.
+ *
+ * For AST2700 A1:
+ * I2C bus interrupts are connected to the OR gate from bit 0 to bit
+ * 15, and the OR gate output pin is connected to the input pin of
+ * GICINT194 of INTCIO (IO Die). Then, the output pin is connected
+ * to the INTC (CPU Die) input pin, and its output pin is connected
+ * to the GIC.
+ *
+ * I2C bus 0 is connected to the OR gate at bit 0.
+ * I2C bus 15 is connected to the OR gate at bit 15.
*/
irq = aspeed_soc_ast2700_get_irq_index(s, ASPEED_DEV_I2C, i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq);
@@ -733,6 +865,17 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
+ /* HACE */
+ object_property_set_link(OBJECT(&s->hace), "dram", OBJECT(s->dram_mr),
+ &error_abort);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
+ return;
+ }
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->hace), 0,
+ sc->memmap[ASPEED_DEV_HACE]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
+ aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
+
create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000);
create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000);
create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000);
@@ -740,7 +883,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("ast2700.io", 0x0, 0x4000000);
}
-static void aspeed_soc_ast2700_class_init(ObjectClass *oc, void *data)
+static void aspeed_soc_ast2700a0_class_init(ObjectClass *oc, void *data)
{
static const char * const valid_cpu_types[] = {
ARM_CPU_TYPE_NAME("cortex-a35"),
@@ -753,7 +896,6 @@ static void aspeed_soc_ast2700_class_init(ObjectClass *oc, void *data)
dc->user_creatable = false;
dc->realize = aspeed_soc_ast2700_realize;
- sc->name = "ast2700-a0";
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2700_A0_SILICON_REV;
sc->sram_size = 0x20000;
@@ -763,7 +905,34 @@ static void aspeed_soc_ast2700_class_init(ObjectClass *oc, void *data)
sc->uarts_num = 13;
sc->num_cpus = 4;
sc->uarts_base = ASPEED_DEV_UART0;
- sc->irqmap = aspeed_soc_ast2700_irqmap;
+ sc->irqmap = aspeed_soc_ast2700a0_irqmap;
+ sc->memmap = aspeed_soc_ast2700_memmap;
+ sc->get_irq = aspeed_soc_ast2700_get_irq;
+}
+
+static void aspeed_soc_ast2700a1_class_init(ObjectClass *oc, void *data)
+{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a35"),
+ NULL
+ };
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
+
+ /* Reason: The Aspeed SoC can only be instantiated from a board */
+ dc->user_creatable = false;
+ dc->realize = aspeed_soc_ast2700_realize;
+
+ sc->valid_cpu_types = valid_cpu_types;
+ sc->silicon_rev = AST2700_A1_SILICON_REV;
+ sc->sram_size = 0x20000;
+ sc->spis_num = 3;
+ sc->wdts_num = 8;
+ sc->macs_num = 3;
+ sc->uarts_num = 13;
+ sc->num_cpus = 4;
+ sc->uarts_base = ASPEED_DEV_UART0;
+ sc->irqmap = aspeed_soc_ast2700a1_irqmap;
sc->memmap = aspeed_soc_ast2700_memmap;
sc->get_irq = aspeed_soc_ast2700_get_irq;
}
@@ -778,7 +947,13 @@ static const TypeInfo aspeed_soc_ast27x0_types[] = {
.name = "ast2700-a0",
.parent = TYPE_ASPEED27X0_SOC,
.instance_init = aspeed_soc_ast2700_init,
- .class_init = aspeed_soc_ast2700_class_init,
+ .class_init = aspeed_soc_ast2700a0_class_init,
+ },
+ {
+ .name = "ast2700-a1",
+ .parent = TYPE_ASPEED27X0_SOC,
+ .instance_init = aspeed_soc_ast2700_init,
+ .class_init = aspeed_soc_ast2700a1_class_init,
},
};
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 126b711..3fd4170 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -14,72 +14,202 @@
#include "hw/registerfields.h"
#include "qapi/error.h"
-/* INTC Registers */
-REG32(GICINT128_EN, 0x1000)
-REG32(GICINT128_STATUS, 0x1004)
-REG32(GICINT129_EN, 0x1100)
-REG32(GICINT129_STATUS, 0x1104)
-REG32(GICINT130_EN, 0x1200)
-REG32(GICINT130_STATUS, 0x1204)
-REG32(GICINT131_EN, 0x1300)
-REG32(GICINT131_STATUS, 0x1304)
-REG32(GICINT132_EN, 0x1400)
-REG32(GICINT132_STATUS, 0x1404)
-REG32(GICINT133_EN, 0x1500)
-REG32(GICINT133_STATUS, 0x1504)
-REG32(GICINT134_EN, 0x1600)
-REG32(GICINT134_STATUS, 0x1604)
-REG32(GICINT135_EN, 0x1700)
-REG32(GICINT135_STATUS, 0x1704)
-REG32(GICINT136_EN, 0x1800)
-REG32(GICINT136_STATUS, 0x1804)
-
-#define GICINT_STATUS_BASE R_GICINT128_STATUS
-
-static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
+/*
+ * INTC Registers
+ *
+ * values below are offset by - 0x1000 from datasheet
+ * because its memory region is start at 0x1000
+ *
+ */
+REG32(GICINT128_EN, 0x000)
+REG32(GICINT128_STATUS, 0x004)
+REG32(GICINT129_EN, 0x100)
+REG32(GICINT129_STATUS, 0x104)
+REG32(GICINT130_EN, 0x200)
+REG32(GICINT130_STATUS, 0x204)
+REG32(GICINT131_EN, 0x300)
+REG32(GICINT131_STATUS, 0x304)
+REG32(GICINT132_EN, 0x400)
+REG32(GICINT132_STATUS, 0x404)
+REG32(GICINT133_EN, 0x500)
+REG32(GICINT133_STATUS, 0x504)
+REG32(GICINT134_EN, 0x600)
+REG32(GICINT134_STATUS, 0x604)
+REG32(GICINT135_EN, 0x700)
+REG32(GICINT135_STATUS, 0x704)
+REG32(GICINT136_EN, 0x800)
+REG32(GICINT136_STATUS, 0x804)
+REG32(GICINT192_201_EN, 0xB00)
+REG32(GICINT192_201_STATUS, 0xB04)
+
+/*
+ * INTCIO Registers
+ *
+ * values below are offset by - 0x100 from datasheet
+ * because its memory region is start at 0x100
+ *
+ */
+REG32(GICINT192_EN, 0x00)
+REG32(GICINT192_STATUS, 0x04)
+REG32(GICINT193_EN, 0x10)
+REG32(GICINT193_STATUS, 0x14)
+REG32(GICINT194_EN, 0x20)
+REG32(GICINT194_STATUS, 0x24)
+REG32(GICINT195_EN, 0x30)
+REG32(GICINT195_STATUS, 0x34)
+REG32(GICINT196_EN, 0x40)
+REG32(GICINT196_STATUS, 0x44)
+REG32(GICINT197_EN, 0x50)
+REG32(GICINT197_STATUS, 0x54)
+
+static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
+ uint32_t reg)
+{
+ int i;
+
+ for (i = 0; i < aic->irq_table_count; i++) {
+ if (aic->irq_table[i].enable_reg == reg ||
+ aic->irq_table[i].status_reg == reg) {
+ return &aic->irq_table[i];
+ }
+ }
+
+ /*
+ * Invalid reg.
+ */
+ g_assert_not_reached();
+}
+
+/*
+ * Update the state of an interrupt controller pin by setting
+ * the specified output pin to the given level.
+ * The input pin index should be between 0 and the number of input pins.
+ * The output pin index should be between 0 and the number of output pins.
+ */
+static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
+ int outpin_idx, int level)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+ const char *name = object_get_typename(OBJECT(s));
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
- return;
+ assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins));
+
+ trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
+ qemu_set_irq(s->output_pins[outpin_idx], level);
+}
+
+static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
+ const AspeedINTCIRQ *intc_irq,
+ uint32_t select)
+{
+ const char *name = object_get_typename(OBJECT(s));
+ uint32_t status_reg;
+ int outpin_idx;
+ int inpin_idx;
+
+ status_reg = intc_irq->status_reg;
+ outpin_idx = intc_irq->outpin_idx;
+ inpin_idx = intc_irq->inpin_idx;
+
+ if (s->mask[inpin_idx] || s->regs[status_reg]) {
+ /*
+ * a. mask is not 0 means in ISR mode
+ * sources interrupt routine are executing.
+ * b. status register value is not 0 means previous
+ * source interrupt does not be executed, yet.
+ *
+ * save source interrupt to pending variable.
+ */
+ s->pending[inpin_idx] |= select;
+ trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
+ } else {
+ /*
+ * notify firmware which source interrupt are coming
+ * by setting status register
+ */
+ s->regs[status_reg] = select;
+ trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+ s->regs[status_reg]);
+ aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
}
+}
+
+static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s,
+ const AspeedINTCIRQ *intc_irq, uint32_t select)
+{
+ const char *name = object_get_typename(OBJECT(s));
+ uint32_t status_reg;
+ int num_outpins;
+ int outpin_idx;
+ int inpin_idx;
+ int i;
- trace_aspeed_intc_update_irq(irq, level);
- qemu_set_irq(s->output_pins[irq], level);
+ num_outpins = intc_irq->num_outpins;
+ status_reg = intc_irq->status_reg;
+ outpin_idx = intc_irq->outpin_idx;
+ inpin_idx = intc_irq->inpin_idx;
+
+ for (i = 0; i < num_outpins; i++) {
+ if (select & BIT(i)) {
+ if (s->mask[inpin_idx] & BIT(i) ||
+ s->regs[status_reg] & BIT(i)) {
+ /*
+ * a. mask bit is not 0 means in ISR mode sources interrupt
+ * routine are executing.
+ * b. status bit is not 0 means previous source interrupt
+ * does not be executed, yet.
+ *
+ * save source interrupt to pending bit.
+ */
+ s->pending[inpin_idx] |= BIT(i);
+ trace_aspeed_intc_pending_irq(name, inpin_idx,
+ s->pending[inpin_idx]);
+ } else {
+ /*
+ * notify firmware which source interrupt are coming
+ * by setting status bit
+ */
+ s->regs[status_reg] |= BIT(i);
+ trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
+ s->regs[status_reg]);
+ aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
+ }
+ }
+ }
}
/*
- * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
- * Utilize "address & 0x0f00" to get the irq and irq output pin index
- * The value of irq should be 0 to num_ints.
- * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
+ * GICINT192_201 maps 1:10 to input IRQ 0 and output IRQs 0 to 9.
+ * GICINT128 to GICINT136 map 1:1 to input IRQs 1 to 9 and output
+ * IRQs 10 to 18. The value of input IRQ should be between 0 and
+ * the number of input pins.
*/
static void aspeed_intc_set_irq(void *opaque, int irq, int level)
{
AspeedINTCState *s = (AspeedINTCState *)opaque;
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t status_addr = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
+ const char *name = object_get_typename(OBJECT(s));
+ const AspeedINTCIRQ *intc_irq;
uint32_t select = 0;
uint32_t enable;
+ int num_outpins;
+ int inpin_idx;
int i;
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
- return;
- }
+ assert(irq < aic->num_inpins);
- trace_aspeed_intc_set_irq(irq, level);
- enable = s->enable[irq];
+ intc_irq = &aic->irq_table[irq];
+ num_outpins = intc_irq->num_outpins;
+ inpin_idx = intc_irq->inpin_idx;
+ trace_aspeed_intc_set_irq(name, inpin_idx, level);
+ enable = s->enable[inpin_idx];
if (!level) {
return;
}
for (i = 0; i < aic->num_lines; i++) {
- if (s->orgates[irq].levels[i]) {
+ if (s->orgates[inpin_idx].levels[i]) {
if (enable & BIT(i)) {
select |= BIT(i);
}
@@ -90,45 +220,190 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
return;
}
- trace_aspeed_intc_select(select);
+ trace_aspeed_intc_select(name, select);
+ if (num_outpins > 1) {
+ aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select);
+ } else {
+ aspeed_intc_set_irq_handler(s, intc_irq, select);
+ }
+}
- if (s->mask[irq] || s->regs[status_addr]) {
- /*
- * a. mask is not 0 means in ISR mode
- * sources interrupt routine are executing.
- * b. status register value is not 0 means previous
- * source interrupt does not be executed, yet.
- *
- * save source interrupt to pending variable.
- */
- s->pending[irq] |= select;
- trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
+static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
+ uint64_t data)
+{
+ AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+ const char *name = object_get_typename(OBJECT(s));
+ const AspeedINTCIRQ *intc_irq;
+ uint32_t reg = offset >> 2;
+ uint32_t old_enable;
+ uint32_t change;
+ int inpin_idx;
+
+ intc_irq = aspeed_intc_get_irq(aic, reg);
+ inpin_idx = intc_irq->inpin_idx;
+
+ assert(inpin_idx < aic->num_inpins);
+
+ /*
+ * The enable registers are used to enable source interrupts.
+ * They also handle masking and unmasking of source interrupts
+ * during the execution of the source ISR.
+ */
+
+ /* disable all source interrupt */
+ if (!data && !s->enable[inpin_idx]) {
+ s->regs[reg] = data;
+ return;
+ }
+
+ old_enable = s->enable[inpin_idx];
+ s->enable[inpin_idx] |= data;
+
+ /* enable new source interrupt */
+ if (old_enable != s->enable[inpin_idx]) {
+ trace_aspeed_intc_enable(name, s->enable[inpin_idx]);
+ s->regs[reg] = data;
+ return;
+ }
+
+ /* mask and unmask source interrupt */
+ change = s->regs[reg] ^ data;
+ if (change & data) {
+ s->mask[inpin_idx] &= ~change;
+ trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]);
} else {
- /*
- * notify firmware which source interrupt are coming
- * by setting status register
- */
- s->regs[status_addr] = select;
- trace_aspeed_intc_trigger_irq(irq, s->regs[status_addr]);
- aspeed_intc_update(s, irq, 1);
+ s->mask[inpin_idx] |= change;
+ trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]);
+ }
+
+ s->regs[reg] = data;
+}
+
+static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
+ uint64_t data)
+{
+ AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+ const char *name = object_get_typename(OBJECT(s));
+ const AspeedINTCIRQ *intc_irq;
+ uint32_t reg = offset >> 2;
+ int outpin_idx;
+ int inpin_idx;
+
+ if (!data) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
+ return;
+ }
+
+ intc_irq = aspeed_intc_get_irq(aic, reg);
+ outpin_idx = intc_irq->outpin_idx;
+ inpin_idx = intc_irq->inpin_idx;
+
+ assert(inpin_idx < aic->num_inpins);
+
+ /* clear status */
+ s->regs[reg] &= ~data;
+
+ /*
+ * These status registers are used for notify sources ISR are executed.
+ * If one source ISR is executed, it will clear one bit.
+ * If it clear all bits, it means to initialize this register status
+ * rather than sources ISR are executed.
+ */
+ if (data == 0xffffffff) {
+ return;
+ }
+
+ /* All source ISR execution are done */
+ if (!s->regs[reg]) {
+ trace_aspeed_intc_all_isr_done(name, inpin_idx);
+ if (s->pending[inpin_idx]) {
+ /*
+ * handle pending source interrupt
+ * notify firmware which source interrupt are pending
+ * by setting status register
+ */
+ s->regs[reg] = s->pending[inpin_idx];
+ s->pending[inpin_idx] = 0;
+ trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+ s->regs[reg]);
+ aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
+ } else {
+ /* clear irq */
+ trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0);
+ aspeed_intc_update(s, inpin_idx, outpin_idx, 0);
+ }
+ }
+}
+
+static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s,
+ hwaddr offset, uint64_t data)
+{
+ const char *name = object_get_typename(OBJECT(s));
+ AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+ const AspeedINTCIRQ *intc_irq;
+ uint32_t reg = offset >> 2;
+ int num_outpins;
+ int outpin_idx;
+ int inpin_idx;
+ int i;
+
+ if (!data) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
+ return;
+ }
+
+ intc_irq = aspeed_intc_get_irq(aic, reg);
+ num_outpins = intc_irq->num_outpins;
+ outpin_idx = intc_irq->outpin_idx;
+ inpin_idx = intc_irq->inpin_idx;
+ assert(inpin_idx < aic->num_inpins);
+
+ /* clear status */
+ s->regs[reg] &= ~data;
+
+ /*
+ * The status registers are used for notify sources ISR are executed.
+ * If one source ISR is executed, it will clear one bit.
+ * If it clear all bits, it means to initialize this register status
+ * rather than sources ISR are executed.
+ */
+ if (data == 0xffffffff) {
+ return;
+ }
+
+ for (i = 0; i < num_outpins; i++) {
+ /* All source ISR executions are done from a specific bit */
+ if (data & BIT(i)) {
+ trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i);
+ if (s->pending[inpin_idx] & BIT(i)) {
+ /*
+ * Handle pending source interrupt.
+ * Notify firmware which source interrupt is pending
+ * by setting the status bit.
+ */
+ s->regs[reg] |= BIT(i);
+ s->pending[inpin_idx] &= ~BIT(i);
+ trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
+ s->regs[reg]);
+ aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
+ } else {
+ /* clear irq for the specific bit */
+ trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx + i, 0);
+ aspeed_intc_update(s, inpin_idx, outpin_idx + i, 0);
+ }
+ }
}
}
static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
{
AspeedINTCState *s = ASPEED_INTC(opaque);
- uint32_t addr = offset >> 2;
+ const char *name = object_get_typename(OBJECT(s));
+ uint32_t reg = offset >> 2;
uint32_t value = 0;
- if (addr >= ASPEED_INTC_NR_REGS) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- return 0;
- }
-
- value = s->regs[addr];
- trace_aspeed_intc_read(offset, size, value);
+ value = s->regs[reg];
+ trace_aspeed_intc_read(name, offset, size, value);
return value;
}
@@ -137,22 +412,12 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
unsigned size)
{
AspeedINTCState *s = ASPEED_INTC(opaque);
- AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t addr = offset >> 2;
- uint32_t old_enable;
- uint32_t change;
- uint32_t irq;
-
- if (addr >= ASPEED_INTC_NR_REGS) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- return;
- }
+ const char *name = object_get_typename(OBJECT(s));
+ uint32_t reg = offset >> 2;
- trace_aspeed_intc_write(offset, size, data);
+ trace_aspeed_intc_write(name, offset, size, data);
- switch (addr) {
+ switch (reg) {
case R_GICINT128_EN:
case R_GICINT129_EN:
case R_GICINT130_EN:
@@ -162,45 +427,8 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
case R_GICINT134_EN:
case R_GICINT135_EN:
case R_GICINT136_EN:
- irq = (offset & 0x0f00) >> 8;
-
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
- return;
- }
-
- /*
- * These registers are used for enable sources interrupt and
- * mask and unmask source interrupt while executing source ISR.
- */
-
- /* disable all source interrupt */
- if (!data && !s->enable[irq]) {
- s->regs[addr] = data;
- return;
- }
-
- old_enable = s->enable[irq];
- s->enable[irq] |= data;
-
- /* enable new source interrupt */
- if (old_enable != s->enable[irq]) {
- trace_aspeed_intc_enable(s->enable[irq]);
- s->regs[addr] = data;
- return;
- }
-
- /* mask and unmask source interrupt */
- change = s->regs[addr] ^ data;
- if (change & data) {
- s->mask[irq] &= ~change;
- trace_aspeed_intc_unmask(change, s->mask[irq]);
- } else {
- s->mask[irq] |= change;
- trace_aspeed_intc_mask(change, s->mask[irq]);
- }
- s->regs[addr] = data;
+ case R_GICINT192_201_EN:
+ aspeed_intc_enable_handler(s, offset, data);
break;
case R_GICINT128_STATUS:
case R_GICINT129_STATUS:
@@ -211,55 +439,68 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
case R_GICINT134_STATUS:
case R_GICINT135_STATUS:
case R_GICINT136_STATUS:
- irq = (offset & 0x0f00) >> 8;
+ aspeed_intc_status_handler(s, offset, data);
+ break;
+ case R_GICINT192_201_STATUS:
+ aspeed_intc_status_handler_multi_outpins(s, offset, data);
+ break;
+ default:
+ s->regs[reg] = data;
+ break;
+ }
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
- return;
- }
+ return;
+}
+
+static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset,
+ unsigned int size)
+{
+ AspeedINTCState *s = ASPEED_INTC(opaque);
+ const char *name = object_get_typename(OBJECT(s));
+ uint32_t reg = offset >> 2;
+ uint32_t value = 0;
- /* clear status */
- s->regs[addr] &= ~data;
+ value = s->regs[reg];
+ trace_aspeed_intc_read(name, offset, size, value);
- /*
- * These status registers are used for notify sources ISR are executed.
- * If one source ISR is executed, it will clear one bit.
- * If it clear all bits, it means to initialize this register status
- * rather than sources ISR are executed.
- */
- if (data == 0xffffffff) {
- return;
- }
+ return value;
+}
- /* All source ISR execution are done */
- if (!s->regs[addr]) {
- trace_aspeed_intc_all_isr_done(irq);
- if (s->pending[irq]) {
- /*
- * handle pending source interrupt
- * notify firmware which source interrupt are pending
- * by setting status register
- */
- s->regs[addr] = s->pending[irq];
- s->pending[irq] = 0;
- trace_aspeed_intc_trigger_irq(irq, s->regs[addr]);
- aspeed_intc_update(s, irq, 1);
- } else {
- /* clear irq */
- trace_aspeed_intc_clear_irq(irq, 0);
- aspeed_intc_update(s, irq, 0);
- }
- }
+static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data,
+ unsigned size)
+{
+ AspeedINTCState *s = ASPEED_INTC(opaque);
+ const char *name = object_get_typename(OBJECT(s));
+ uint32_t reg = offset >> 2;
+
+ trace_aspeed_intc_write(name, offset, size, data);
+
+ switch (reg) {
+ case R_GICINT192_EN:
+ case R_GICINT193_EN:
+ case R_GICINT194_EN:
+ case R_GICINT195_EN:
+ case R_GICINT196_EN:
+ case R_GICINT197_EN:
+ aspeed_intc_enable_handler(s, offset, data);
+ break;
+ case R_GICINT192_STATUS:
+ case R_GICINT193_STATUS:
+ case R_GICINT194_STATUS:
+ case R_GICINT195_STATUS:
+ case R_GICINT196_STATUS:
+ case R_GICINT197_STATUS:
+ aspeed_intc_status_handler(s, offset, data);
break;
default:
- s->regs[addr] = data;
+ s->regs[reg] = data;
break;
}
return;
}
+
static const MemoryRegionOps aspeed_intc_ops = {
.read = aspeed_intc_read,
.write = aspeed_intc_write,
@@ -270,14 +511,24 @@ static const MemoryRegionOps aspeed_intc_ops = {
}
};
+static const MemoryRegionOps aspeed_intcio_ops = {
+ .read = aspeed_intcio_read,
+ .write = aspeed_intcio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ }
+};
+
static void aspeed_intc_instance_init(Object *obj)
{
AspeedINTCState *s = ASPEED_INTC(obj);
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
- assert(aic->num_ints <= ASPEED_INTC_NR_INTS);
- for (i = 0; i < aic->num_ints; i++) {
+ assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS);
+ for (i = 0; i < aic->num_inpins; i++) {
object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
TYPE_OR_IRQ);
object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
@@ -288,8 +539,9 @@ static void aspeed_intc_instance_init(Object *obj)
static void aspeed_intc_reset(DeviceState *dev)
{
AspeedINTCState *s = ASPEED_INTC(dev);
+ AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- memset(s->regs, 0, sizeof(s->regs));
+ memset(s->regs, 0, aic->nr_regs << 2);
memset(s->enable, 0, sizeof(s->enable));
memset(s->mask, 0, sizeof(s->mask));
memset(s->pending, 0, sizeof(s->pending));
@@ -302,28 +554,51 @@ static void aspeed_intc_realize(DeviceState *dev, Error **errp)
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
- memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
- TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
+ memory_region_init(&s->iomem_container, OBJECT(s),
+ TYPE_ASPEED_INTC ".container", aic->mem_size);
+
+ sysbus_init_mmio(sbd, &s->iomem_container);
- sysbus_init_mmio(sbd, &s->iomem);
- qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
+ s->regs = g_new(uint32_t, aic->nr_regs);
+ memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s,
+ TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
- for (i = 0; i < aic->num_ints; i++) {
+ memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
+ &s->iomem);
+
+ qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins);
+
+ for (i = 0; i < aic->num_inpins; i++) {
if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
return;
}
+ }
+
+ for (i = 0; i < aic->num_outpins; i++) {
sysbus_init_irq(sbd, &s->output_pins[i]);
}
}
+static void aspeed_intc_unrealize(DeviceState *dev)
+{
+ AspeedINTCState *s = ASPEED_INTC(dev);
+
+ g_free(s->regs);
+ s->regs = NULL;
+}
+
static void aspeed_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
dc->desc = "ASPEED INTC Controller";
dc->realize = aspeed_intc_realize;
+ dc->unrealize = aspeed_intc_unrealize;
device_class_set_legacy_reset(dc, aspeed_intc_reset);
dc->vmsd = NULL;
+
+ aic->reg_ops = &aspeed_intc_ops;
}
static const TypeInfo aspeed_intc_info = {
@@ -336,6 +611,19 @@ static const TypeInfo aspeed_intc_info = {
.abstract = true,
};
+static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
+ {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS},
+ {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS},
+ {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS},
+ {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS},
+ {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS},
+ {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS},
+ {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS},
+ {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS},
+ {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS},
+ {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS},
+};
+
static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -343,7 +631,13 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)
dc->desc = "ASPEED 2700 INTC Controller";
aic->num_lines = 32;
- aic->num_ints = 9;
+ aic->num_inpins = 10;
+ aic->num_outpins = 19;
+ aic->mem_size = 0x4000;
+ aic->nr_regs = 0xB08 >> 2;
+ aic->reg_offset = 0x1000;
+ aic->irq_table = aspeed_2700_intc_irqs;
+ aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs);
}
static const TypeInfo aspeed_2700_intc_info = {
@@ -352,10 +646,43 @@ static const TypeInfo aspeed_2700_intc_info = {
.class_init = aspeed_2700_intc_class_init,
};
+static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
+ {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS},
+ {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS},
+ {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS},
+ {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS},
+ {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS},
+ {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS},
+};
+
+static void aspeed_2700_intcio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 INTC IO Controller";
+ aic->num_lines = 32;
+ aic->num_inpins = 6;
+ aic->num_outpins = 6;
+ aic->mem_size = 0x400;
+ aic->nr_regs = 0x58 >> 2;
+ aic->reg_offset = 0x100;
+ aic->reg_ops = &aspeed_intcio_ops;
+ aic->irq_table = aspeed_2700_intcio_irqs;
+ aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs);
+}
+
+static const TypeInfo aspeed_2700_intcio_info = {
+ .name = TYPE_ASPEED_2700_INTCIO,
+ .parent = TYPE_ASPEED_INTC,
+ .class_init = aspeed_2700_intcio_class_init,
+};
+
static void aspeed_intc_register_types(void)
{
type_register_static(&aspeed_intc_info);
type_register_static(&aspeed_2700_intc_info);
+ type_register_static(&aspeed_2700_intcio_info);
}
type_init(aspeed_intc_register_types);
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 3dcf147..913197a 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -80,18 +80,19 @@ aspeed_vic_update_irq(int flags) "Raising IRQ: %d"
aspeed_vic_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
# aspeed_intc.c
-aspeed_intc_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
-aspeed_intc_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
-aspeed_intc_set_irq(int irq, int level) "Set IRQ %d: %d"
-aspeed_intc_clear_irq(int irq, int level) "Clear IRQ %d: %d"
-aspeed_intc_update_irq(int irq, int level) "Update IRQ: %d: %d"
-aspeed_intc_pending_irq(int irq, uint32_t value) "Pending IRQ: %d: 0x%x"
-aspeed_intc_trigger_irq(int irq, uint32_t value) "Trigger IRQ: %d: 0x%x"
-aspeed_intc_all_isr_done(int irq) "All source ISR execution are done: %d"
-aspeed_intc_enable(uint32_t value) "Enable: 0x%x"
-aspeed_intc_select(uint32_t value) "Select: 0x%x"
-aspeed_intc_mask(uint32_t change, uint32_t value) "Mask: 0x%x: 0x%x"
-aspeed_intc_unmask(uint32_t change, uint32_t value) "UnMask: 0x%x: 0x%x"
+aspeed_intc_read(const char *s, uint64_t offset, unsigned size, uint32_t value) "%s: From 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_intc_write(const char *s, uint64_t offset, unsigned size, uint32_t data) "%s: To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_intc_set_irq(const char *s, int inpin_idx, int level) "%s: Set IRQ %d: %d"
+aspeed_intc_clear_irq(const char *s, int inpin_idx, int outpin_idx, int level) "%s: Clear IRQ %d-%d: %d"
+aspeed_intc_update_irq(const char *s, int inpin_idx, int outpin_idx, int level) "%s: Update IRQ: %d-%d: %d"
+aspeed_intc_pending_irq(const char *s, int inpin_idx, uint32_t value) "%s: Pending IRQ: %d: 0x%x"
+aspeed_intc_trigger_irq(const char *s, int inpin_idx, int outpin_idx, uint32_t value) "%s: Trigger IRQ: %d-%d: 0x%x"
+aspeed_intc_all_isr_done(const char *s, int inpin_idx) "%s: All source ISR execution are done: %d"
+aspeed_intc_enable(const char *s, uint32_t value) "%s: Enable: 0x%x"
+aspeed_intc_select(const char *s, uint32_t value) "%s: Select: 0x%x"
+aspeed_intc_mask(const char *s, uint32_t change, uint32_t value) "%s: Mask: 0x%x: 0x%x"
+aspeed_intc_unmask(const char *s, uint32_t change, uint32_t value) "%s: UnMask: 0x%x: 0x%x"
+aspeed_intc_all_isr_done_bit(const char *s, int inpin_idx, int bit) "%s: All source ISR execution are done from specific bit: %d-%d"
# arm_gic.c
gic_enable_irq(int irq) "irq %d enabled"
diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
index e3f7df2..32a5dbd 100644
--- a/hw/misc/aspeed_hace.c
+++ b/hw/misc/aspeed_hace.c
@@ -59,6 +59,7 @@
/* Other cmd bits */
#define HASH_IRQ_EN BIT(9)
#define HASH_SG_EN BIT(18)
+#define CRYPT_IRQ_EN BIT(12)
/* Scatter-gather data list */
#define SG_LIST_LEN_SIZE 4
#define SG_LIST_LEN_MASK 0x0FFFFFFF
@@ -75,9 +76,12 @@ static const struct {
{ HASH_ALGO_SHA1, QCRYPTO_HASH_ALGO_SHA1 },
{ HASH_ALGO_SHA224, QCRYPTO_HASH_ALGO_SHA224 },
{ HASH_ALGO_SHA256, QCRYPTO_HASH_ALGO_SHA256 },
- { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA512, QCRYPTO_HASH_ALGO_SHA512 },
- { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA384, QCRYPTO_HASH_ALGO_SHA384 },
- { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA256, QCRYPTO_HASH_ALGO_SHA256 },
+ { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA512,
+ QCRYPTO_HASH_ALGO_SHA512 },
+ { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA384,
+ QCRYPTO_HASH_ALGO_SHA384 },
+ { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA256,
+ QCRYPTO_HASH_ALGO_SHA256 },
};
static int hash_algo_lookup(uint32_t reg)
@@ -201,7 +205,8 @@ static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode,
haddr = address_space_map(&s->dram_as, addr, &plen, false,
MEMTXATTRS_UNSPECIFIED);
if (haddr == NULL) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto failed\n", __func__);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: qcrypto failed\n", __func__);
return;
}
iov[i].iov_base = haddr;
@@ -339,6 +344,15 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data,
qemu_irq_lower(s->irq);
}
}
+ if (ahc->raise_crypt_interrupt_workaround) {
+ if (data & CRYPT_IRQ) {
+ data &= ~CRYPT_IRQ;
+
+ if (s->regs[addr] & CRYPT_IRQ) {
+ qemu_irq_lower(s->irq);
+ }
+ }
+ }
break;
case R_HASH_SRC:
data &= ahc->src_mask;
@@ -384,6 +398,12 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data,
case R_CRYPT_CMD:
qemu_log_mask(LOG_UNIMP, "%s: Crypt commands not implemented\n",
__func__);
+ if (ahc->raise_crypt_interrupt_workaround) {
+ s->regs[R_STATUS] |= CRYPT_IRQ;
+ if (data & CRYPT_IRQ_EN) {
+ qemu_irq_raise(s->irq);
+ }
+ }
break;
default:
break;
@@ -548,12 +568,39 @@ static const TypeInfo aspeed_ast1030_hace_info = {
.class_init = aspeed_ast1030_hace_class_init,
};
+static void aspeed_ast2700_hace_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass);
+
+ dc->desc = "AST2700 Hash and Crypto Engine";
+
+ ahc->src_mask = 0x7FFFFFFF;
+ ahc->dest_mask = 0x7FFFFFF8;
+ ahc->key_mask = 0x7FFFFFF8;
+ ahc->hash_mask = 0x00147FFF;
+
+ /*
+ * Currently, it does not support the CRYPT command. Instead, it only
+ * sends an interrupt to notify the firmware that the crypt command
+ * has completed. It is a temporary workaround.
+ */
+ ahc->raise_crypt_interrupt_workaround = true;
+}
+
+static const TypeInfo aspeed_ast2700_hace_info = {
+ .name = TYPE_ASPEED_AST2700_HACE,
+ .parent = TYPE_ASPEED_HACE,
+ .class_init = aspeed_ast2700_hace_class_init,
+};
+
static void aspeed_hace_register_types(void)
{
type_register_static(&aspeed_ast2400_hace_info);
type_register_static(&aspeed_ast2500_hace_info);
type_register_static(&aspeed_ast2600_hace_info);
type_register_static(&aspeed_ast1030_hace_info);
+ type_register_static(&aspeed_ast2700_hace_info);
type_register_static(&aspeed_hace_info);
}
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index bac1441..76cfd91 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -157,6 +157,7 @@
#define AST2700_SCU_FREQ_CNTR TO_REG(0x3b0)
#define AST2700_SCU_CPU_SCRATCH_0 TO_REG(0x780)
#define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784)
+#define AST2700_SCU_VGA_SCRATCH_0 TO_REG(0x900)
#define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
#define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
@@ -559,6 +560,8 @@ static uint32_t aspeed_silicon_revs[] = {
AST2700_A0_SILICON_REV,
AST2720_A0_SILICON_REV,
AST2750_A0_SILICON_REV,
+ AST2700_A1_SILICON_REV,
+ AST2750_A1_SILICON_REV,
};
bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -909,8 +912,6 @@ static const MemoryRegionOps aspeed_ast2700_scu_ops = {
};
static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
- [AST2700_SILICON_REV] = AST2700_A0_SILICON_REV,
- [AST2700_HW_STRAP1] = 0x00000800,
[AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
[AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
[AST2700_HW_STRAP1_SEC1] = 0x000000FF,
@@ -930,6 +931,7 @@ static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
[AST2700_SCU_FREQ_CNTR] = 0x000375eb,
[AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
[AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
+ [AST2700_SCU_VGA_SCRATCH_0] = 0x00000040,
};
static void aspeed_ast2700_scu_reset(DeviceState *dev)
@@ -938,6 +940,8 @@ static void aspeed_ast2700_scu_reset(DeviceState *dev)
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
memcpy(s->regs, asc->resets, asc->nr_regs * 4);
+ s->regs[AST2700_SILICON_REV] = s->silicon_rev;
+ s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
}
static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
@@ -1030,8 +1034,6 @@ static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
};
static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
- [AST2700_SILICON_REV] = 0x06000003,
- [AST2700_HW_STRAP1] = 0x00000504,
[AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
[AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
[AST2700_HW_STRAP1_SEC1] = 0x000000FF,
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 689f52d..f899356 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -128,7 +128,7 @@ struct Aspeed27x0SoCState {
AspeedSoCState parent;
ARMCPU cpu[ASPEED_CPUS_NUM];
- AspeedINTCState intc;
+ AspeedINTCState intc[2];
GICv3State gic;
MemoryRegion dram_empty;
};
@@ -148,7 +148,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(Aspeed10x0SoCState, ASPEED10X0_SOC)
struct AspeedSoCClass {
DeviceClass parent_class;
- const char *name;
/** valid_cpu_types: NULL terminated array of a single CPU type. */
const char * const *valid_cpu_types;
uint32_t silicon_rev;
@@ -195,6 +194,7 @@ enum {
ASPEED_DEV_EHCI2,
ASPEED_DEV_VIC,
ASPEED_DEV_INTC,
+ ASPEED_DEV_INTCIO,
ASPEED_DEV_SDMC,
ASPEED_DEV_SCU,
ASPEED_DEV_ADC,
diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 18cb434..3727ba2 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -14,10 +14,19 @@
#define TYPE_ASPEED_INTC "aspeed.intc"
#define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
+#define TYPE_ASPEED_2700_INTCIO TYPE_ASPEED_INTC "io-ast2700"
OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
-#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
-#define ASPEED_INTC_NR_INTS 9
+#define ASPEED_INTC_MAX_INPINS 10
+#define ASPEED_INTC_MAX_OUTPINS 19
+
+typedef struct AspeedINTCIRQ {
+ int inpin_idx;
+ int outpin_idx;
+ int num_outpins;
+ uint32_t enable_reg;
+ uint32_t status_reg;
+} AspeedINTCIRQ;
struct AspeedINTCState {
/*< private >*/
@@ -25,20 +34,29 @@ struct AspeedINTCState {
/*< public >*/
MemoryRegion iomem;
- uint32_t regs[ASPEED_INTC_NR_REGS];
- OrIRQState orgates[ASPEED_INTC_NR_INTS];
- qemu_irq output_pins[ASPEED_INTC_NR_INTS];
+ MemoryRegion iomem_container;
+
+ uint32_t *regs;
+ OrIRQState orgates[ASPEED_INTC_MAX_INPINS];
+ qemu_irq output_pins[ASPEED_INTC_MAX_OUTPINS];
- uint32_t enable[ASPEED_INTC_NR_INTS];
- uint32_t mask[ASPEED_INTC_NR_INTS];
- uint32_t pending[ASPEED_INTC_NR_INTS];
+ uint32_t enable[ASPEED_INTC_MAX_INPINS];
+ uint32_t mask[ASPEED_INTC_MAX_INPINS];
+ uint32_t pending[ASPEED_INTC_MAX_INPINS];
};
struct AspeedINTCClass {
SysBusDeviceClass parent_class;
uint32_t num_lines;
- uint32_t num_ints;
+ uint32_t num_inpins;
+ uint32_t num_outpins;
+ uint64_t mem_size;
+ uint64_t nr_regs;
+ uint64_t reg_offset;
+ const MemoryRegionOps *reg_ops;
+ const AspeedINTCIRQ *irq_table;
+ int irq_table_count;
};
#endif /* ASPEED_INTC_H */
diff --git a/include/hw/misc/aspeed_hace.h b/include/hw/misc/aspeed_hace.h
index 4af9919..5d4aa19 100644
--- a/include/hw/misc/aspeed_hace.h
+++ b/include/hw/misc/aspeed_hace.h
@@ -18,6 +18,7 @@
#define TYPE_ASPEED_AST2500_HACE TYPE_ASPEED_HACE "-ast2500"
#define TYPE_ASPEED_AST2600_HACE TYPE_ASPEED_HACE "-ast2600"
#define TYPE_ASPEED_AST1030_HACE TYPE_ASPEED_HACE "-ast1030"
+#define TYPE_ASPEED_AST2700_HACE TYPE_ASPEED_HACE "-ast2700"
OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE)
@@ -49,6 +50,7 @@ struct AspeedHACEClass {
uint32_t dest_mask;
uint32_t key_mask;
uint32_t hash_mask;
+ bool raise_crypt_interrupt_workaround;
};
#endif /* ASPEED_HACE_H */
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index 356be95..684b48b 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -54,6 +54,8 @@ struct AspeedSCUState {
#define AST2700_A0_SILICON_REV 0x06000103U
#define AST2720_A0_SILICON_REV 0x06000203U
#define AST2750_A0_SILICON_REV 0x06000003U
+#define AST2700_A1_SILICON_REV 0x06010103U
+#define AST2750_A1_SILICON_REV 0x06010003U
#define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04)
diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py
index b52358b..77dc893 100644
--- a/tests/functional/aspeed.py
+++ b/tests/functional/aspeed.py
@@ -7,21 +7,23 @@ from qemu_test import LinuxKernelTest
class AspeedTest(LinuxKernelTest):
- def do_test_arm_aspeed(self, machine, image):
+ def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04',
+ cpu_id='0x0', soc='AST2500 rev A1'):
+ hostname = machine.removesuffix('-bmc')
+
self.set_machine(machine)
self.vm.set_console()
- self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
- '-net', 'nic', '-snapshot')
+ self.vm.add_args('-drive', f'file={image},if=mtd,format=raw',
+ '-snapshot')
self.vm.launch()
- self.wait_for_console_pattern("U-Boot 2016.07")
- self.wait_for_console_pattern("## Loading kernel from FIT Image at 20080000")
- self.wait_for_console_pattern("Starting kernel ...")
- self.wait_for_console_pattern("Booting Linux on physical CPU 0x0")
- self.wait_for_console_pattern(
- "aspeed-smc 1e620000.spi: read control register: 203b0641")
- self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ")
- self.wait_for_console_pattern("systemd[1]: Set hostname to")
+ self.wait_for_console_pattern(f'U-Boot {uboot}')
+ self.wait_for_console_pattern('## Loading kernel from FIT Image')
+ self.wait_for_console_pattern('Starting kernel ...')
+ self.wait_for_console_pattern(f'Booting Linux on physical CPU {cpu_id}')
+ self.wait_for_console_pattern(f'ASPEED {soc}')
+ self.wait_for_console_pattern('/init as init process')
+ self.wait_for_console_pattern(f'systemd[1]: Hostname set to <{hostname}>.')
def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB'):
self.require_netdev('user')
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 97c3f4a..5dc66c0 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -22,8 +22,10 @@ test_timeouts = {
'acpi_bits' : 420,
'arm_aspeed_palmetto' : 120,
'arm_aspeed_romulus' : 120,
+ 'arm_aspeed_witherspoon' : 120,
'arm_aspeed_ast2500' : 720,
'arm_aspeed_ast2600' : 1200,
+ 'arm_aspeed_bletchley' : 120,
'arm_aspeed_rainier' : 480,
'arm_bpim2u' : 500,
'arm_collie' : 180,
@@ -104,8 +106,10 @@ tests_arm_system_thorough = [
'arm_aspeed_ast1030',
'arm_aspeed_palmetto',
'arm_aspeed_romulus',
+ 'arm_aspeed_witherspoon',
'arm_aspeed_ast2500',
'arm_aspeed_ast2600',
+ 'arm_aspeed_bletchley',
'arm_aspeed_rainier',
'arm_bpim2u',
'arm_canona1100',
diff --git a/tests/functional/test_aarch64_aspeed.py b/tests/functional/test_aarch64_aspeed.py
index 9595498..c25c966 100755
--- a/tests/functional/test_aarch64_aspeed.py
+++ b/tests/functional/test_aarch64_aspeed.py
@@ -27,37 +27,37 @@ class AST2x00MachineSDK(QemuSystemTest):
wait_for_console_pattern(self, '## Loading kernel from FIT Image')
wait_for_console_pattern(self, 'Starting kernel ...')
- ASSET_SDK_V903_AST2700 = Asset(
- 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.03/ast2700-default-obmc.tar.gz',
- '91225f50d255e2905ba8d8e0c80b71b9d157c3609770c7a740cd786370d85a77')
+ ASSET_SDK_V905_AST2700 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/ast2700-a0-default-obmc.tar.gz',
+ 'cfbbd1cce72f2a3b73b9080c41eecdadebb7077fba4f7806d72ac99f3e84b74a')
- def test_aarch64_ast2700_evb_sdk_v09_03(self):
- self.set_machine('ast2700-evb')
-
- self.archive_extract(self.ASSET_SDK_V903_AST2700)
+ ASSET_SDK_V905_AST2700A1 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/ast2700-default-obmc.tar.gz',
+ 'c1f4496aec06743c812a6e9a1a18d032f34d62f3ddb6956e924fef62aa2046a5')
+ def start_ast2700_test(self, name):
num_cpu = 4
- uboot_size = os.path.getsize(self.scratch_file('ast2700-default',
+ uboot_size = os.path.getsize(self.scratch_file(name,
'u-boot-nodtb.bin'))
uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
load_images_list = [
{
'addr': '0x400000000',
- 'file': self.scratch_file('ast2700-default',
+ 'file': self.scratch_file(name,
'u-boot-nodtb.bin')
},
{
'addr': str(uboot_dtb_load_addr),
- 'file': self.scratch_file('ast2700-default', 'u-boot.dtb')
+ 'file': self.scratch_file(name, 'u-boot.dtb')
},
{
'addr': '0x430000000',
- 'file': self.scratch_file('ast2700-default', 'bl31.bin')
+ 'file': self.scratch_file(name, 'bl31.bin')
},
{
'addr': '0x430080000',
- 'file': self.scratch_file('ast2700-default', 'optee',
+ 'file': self.scratch_file(name, 'optee',
'tee-raw.bin')
}
]
@@ -76,23 +76,34 @@ class AST2x00MachineSDK(QemuSystemTest):
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
self.do_test_aarch64_aspeed_sdk_start(
- self.scratch_file('ast2700-default', 'image-bmc'))
+ self.scratch_file(name, 'image-bmc'))
- wait_for_console_pattern(self, 'ast2700-default login:')
+ wait_for_console_pattern(self, f'{name} login:')
exec_command_and_wait_for_pattern(self, 'root', 'Password:')
- exec_command_and_wait_for_pattern(self,
- '0penBmc', 'root@ast2700-default:~#')
+ exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#')
exec_command_and_wait_for_pattern(self,
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ',
'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d');
exec_command_and_wait_for_pattern(self,
- 'cat /sys/class/hwmon/hwmon20/temp1_input', '0')
+ 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0')
self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000)
exec_command_and_wait_for_pattern(self,
- 'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')
+ 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000')
+
+ def test_aarch64_ast2700_evb_sdk_v09_05(self):
+ self.set_machine('ast2700-evb')
+
+ self.archive_extract(self.ASSET_SDK_V905_AST2700)
+ self.start_ast2700_test('ast2700-a0-default')
+
+ def test_aarch64_ast2700a1_evb_sdk_v09_05(self):
+ self.set_machine('ast2700a1-evb')
+
+ self.archive_extract(self.ASSET_SDK_V905_AST2700A1)
+ self.start_ast2700_test('ast2700-default')
if __name__ == '__main__':
diff --git a/tests/functional/test_arm_aspeed_bletchley.py b/tests/functional/test_arm_aspeed_bletchley.py
new file mode 100644
index 0000000..0da856c
--- /dev/null
+++ b/tests/functional/test_arm_aspeed_bletchley.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class BletchleyMachine(AspeedTest):
+
+ ASSET_BLETCHLEY_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/bletchley-bmc/openbmc-20250128071329/obmc-phosphor-image-bletchley-20250128071329.static.mtd.xz',
+ 'db21d04d47d7bb2a276f59d308614b4dfb70b9c7c81facbbca40a3977a2d8844');
+
+ def test_arm_ast2600_bletchley_openbmc(self):
+ image_path = self.uncompress(self.ASSET_BLETCHLEY_FLASH)
+
+ self.do_test_arm_aspeed_openbmc('bletchley-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0xf00',
+ soc='AST2600 rev A3');
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/test_arm_aspeed_palmetto.py b/tests/functional/test_arm_aspeed_palmetto.py
index 6588c02..35d832b 100755
--- a/tests/functional/test_arm_aspeed_palmetto.py
+++ b/tests/functional/test_arm_aspeed_palmetto.py
@@ -7,18 +7,19 @@
from qemu_test import Asset
from aspeed import AspeedTest
+
class PalmettoMachine(AspeedTest):
ASSET_PALMETTO_FLASH = Asset(
- ('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
- 'obmc-phosphor-image-palmetto.static.mtd'),
- '3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d');
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/palmetto-bmc/openbmc-20250128071432/obmc-phosphor-image-palmetto-20250128071432.static.mtd',
+ 'bce7c392eec75c707a91cfc8fad7ca9a69d7e4f10df936930d65c1cb9897ac81');
- def test_arm_ast2400_palmetto_openbmc_v2_9_0(self):
+ def test_arm_ast2400_palmetto_openbmc(self):
image_path = self.ASSET_PALMETTO_FLASH.fetch()
- self.do_test_arm_aspeed('palmetto-bmc', image_path)
-
+ self.do_test_arm_aspeed_openbmc('palmetto-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0x0',
+ soc='AST2400 rev A1');
if __name__ == '__main__':
AspeedTest.main()
diff --git a/tests/functional/test_arm_aspeed_romulus.py b/tests/functional/test_arm_aspeed_romulus.py
index 747b616..b97ed95 100755
--- a/tests/functional/test_arm_aspeed_romulus.py
+++ b/tests/functional/test_arm_aspeed_romulus.py
@@ -7,18 +7,19 @@
from qemu_test import Asset
from aspeed import AspeedTest
+
class RomulusMachine(AspeedTest):
ASSET_ROMULUS_FLASH = Asset(
- ('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
- 'obmc-phosphor-image-romulus.static.mtd'),
- '820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25')
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/romulus-bmc/openbmc-20250128071340/obmc-phosphor-image-romulus-20250128071340.static.mtd',
+ '6d031376440c82ed9d087d25e9fa76aea75b42f80daa252ec402c0bc3cf6cf5b');
- def test_arm_ast2500_romulus_openbmc_v2_9_0(self):
+ def test_arm_ast2500_romulus_openbmc(self):
image_path = self.ASSET_ROMULUS_FLASH.fetch()
- self.do_test_arm_aspeed('romulus-bmc', image_path)
-
+ self.do_test_arm_aspeed_openbmc('romulus-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0x0',
+ soc='AST2500 rev A1');
if __name__ == '__main__':
AspeedTest.main()
diff --git a/tests/functional/test_arm_aspeed_witherspoon.py b/tests/functional/test_arm_aspeed_witherspoon.py
new file mode 100644
index 0000000..ea1ce89
--- /dev/null
+++ b/tests/functional/test_arm_aspeed_witherspoon.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class WitherspoonMachine(AspeedTest):
+
+ ASSET_WITHERSPOON_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/witherspoon-bmc/openbmc-20240618035022/obmc-phosphor-image-witherspoon-20240618035022.ubi.mtd',
+ '937d9ed449ea6c6cbed983519088a42d0cafe276bcfe4fce07772ca6673f9213');
+
+ def test_arm_ast2500_witherspoon_openbmc(self):
+ image_path = self.ASSET_WITHERSPOON_FLASH.fetch()
+
+ self.do_test_arm_aspeed_openbmc('witherspoon-bmc', image=image_path,
+ uboot='2016.07', cpu_id='0x0',
+ soc='AST2500 rev A1');
+
+if __name__ == '__main__':
+ AspeedTest.main()