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-----

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>
This commit is contained in:
Stefan Hajnoczi 2025-03-10 13:40:35 +08:00
commit 2e14ac3c9c
22 changed files with 1160 additions and 357 deletions

136
docs/specs/aspeed-intc.rst Normal file
View File

@ -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 | |
| |-----------| |
| |
|-------------------------------------------------------------------------------------------------------|

View File

@ -38,3 +38,4 @@ guest hardware that is specific to QEMU.
rocker
riscv-iommu
riscv-aia
aspeed-intc

View File

@ -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_ast2700_evb_class_init,
.class_init = aspeed_machine_ast2700a0_evb_class_init,
}, {
.name = MACHINE_TYPE_NAME("ast2700a1-evb"),
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_ast2700a1_evb_class_init,
#endif
}, {
.name = TYPE_ASPEED_MACHINE,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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,57 +67,21 @@ 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[] = {
[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,
[ASPEED_DEV_UART8] = 132,
[ASPEED_DEV_UART9] = 132,
[ASPEED_DEV_UART10] = 132,
[ASPEED_DEV_UART11] = 132,
[ASPEED_DEV_UART12] = 132,
[ASPEED_DEV_FMC] = 131,
static const int aspeed_soc_ast2700a0_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 +90,104 @@ 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_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_PECI] = 133,
[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_UART5] = 132,
[ASPEED_DEV_UART6] = 132,
[ASPEED_DEV_UART7] = 132,
[ASPEED_DEV_UART8] = 132,
[ASPEED_DEV_UART9] = 132,
[ASPEED_DEV_UART10] = 132,
[ASPEED_DEV_UART11] = 132,
[ASPEED_DEV_UART12] = 132,
[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_PECI] = 133,
[ASPEED_DEV_SDHCI] = 133,
};
static const int aspeed_soc_ast2700a1_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] = 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,
},
};

View File

@ -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)
/*
* 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)
#define GICINT_STATUS_BASE R_GICINT128_STATUS
/*
* 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 void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
uint32_t reg)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
if (irq >= aic->num_ints) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
__func__, irq);
return;
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];
}
trace_aspeed_intc_update_irq(irq, level);
qemu_set_irq(s->output_pins[irq], level);
}
/*
* 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.
* 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));
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;
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);
}
}
}
}
/*
* 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,137 +220,88 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
return;
}
trace_aspeed_intc_select(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]);
trace_aspeed_intc_select(name, select);
if (num_outpins > 1) {
aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select);
} 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);
aspeed_intc_set_irq_handler(s, intc_irq, select);
}
}
static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
uint64_t data)
{
AspeedINTCState *s = ASPEED_INTC(opaque);
uint32_t addr = 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);
return value;
}
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;
const char *name = object_get_typename(OBJECT(s));
const AspeedINTCIRQ *intc_irq;
uint32_t reg = offset >> 2;
uint32_t old_enable;
uint32_t change;
uint32_t irq;
int inpin_idx;
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;
}
intc_irq = aspeed_intc_get_irq(aic, reg);
inpin_idx = intc_irq->inpin_idx;
trace_aspeed_intc_write(offset, size, data);
switch (addr) {
case R_GICINT128_EN:
case R_GICINT129_EN:
case R_GICINT130_EN:
case R_GICINT131_EN:
case R_GICINT132_EN:
case R_GICINT133_EN:
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;
}
assert(inpin_idx < aic->num_inpins);
/*
* These registers are used for enable sources interrupt and
* mask and unmask source interrupt while executing source ISR.
* 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[irq]) {
s->regs[addr] = data;
if (!data && !s->enable[inpin_idx]) {
s->regs[reg] = data;
return;
}
old_enable = s->enable[irq];
s->enable[irq] |= data;
old_enable = s->enable[inpin_idx];
s->enable[inpin_idx] |= data;
/* enable new source interrupt */
if (old_enable != s->enable[irq]) {
trace_aspeed_intc_enable(s->enable[irq]);
s->regs[addr] = data;
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[addr] ^ data;
change = s->regs[reg] ^ data;
if (change & data) {
s->mask[irq] &= ~change;
trace_aspeed_intc_unmask(change, s->mask[irq]);
s->mask[inpin_idx] &= ~change;
trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]);
} else {
s->mask[irq] |= change;
trace_aspeed_intc_mask(change, s->mask[irq]);
s->mask[inpin_idx] |= change;
trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]);
}
s->regs[addr] = data;
break;
case R_GICINT128_STATUS:
case R_GICINT129_STATUS:
case R_GICINT130_STATUS:
case R_GICINT131_STATUS:
case R_GICINT132_STATUS:
case R_GICINT133_STATUS:
case R_GICINT134_STATUS:
case R_GICINT135_STATUS:
case R_GICINT136_STATUS:
irq = (offset & 0x0f00) >> 8;
if (irq >= aic->num_ints) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
__func__, irq);
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[addr] &= ~data;
s->regs[reg] &= ~data;
/*
* These status registers are used for notify sources ISR are executed.
@ -233,33 +314,193 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
}
/* All source ISR execution are done */
if (!s->regs[addr]) {
trace_aspeed_intc_all_isr_done(irq);
if (s->pending[irq]) {
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[addr] = s->pending[irq];
s->pending[irq] = 0;
trace_aspeed_intc_trigger_irq(irq, s->regs[addr]);
aspeed_intc_update(s, irq, 1);
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(irq, 0);
aspeed_intc_update(s, irq, 0);
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);
const char *name = object_get_typename(OBJECT(s));
uint32_t reg = offset >> 2;
uint32_t value = 0;
value = s->regs[reg];
trace_aspeed_intc_read(name, offset, size, value);
return value;
}
static void aspeed_intc_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_GICINT128_EN:
case R_GICINT129_EN:
case R_GICINT130_EN:
case R_GICINT131_EN:
case R_GICINT132_EN:
case R_GICINT133_EN:
case R_GICINT134_EN:
case R_GICINT135_EN:
case R_GICINT136_EN:
case R_GICINT192_201_EN:
aspeed_intc_enable_handler(s, offset, data);
break;
case R_GICINT128_STATUS:
case R_GICINT129_STATUS:
case R_GICINT130_STATUS:
case R_GICINT131_STATUS:
case R_GICINT132_STATUS:
case R_GICINT133_STATUS:
case R_GICINT134_STATUS:
case R_GICINT135_STATUS:
case R_GICINT136_STATUS:
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[addr] = data;
s->regs[reg] = data;
break;
}
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;
value = s->regs[reg];
trace_aspeed_intc_read(name, offset, size, value);
return value;
}
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[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);
qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
sysbus_init_mmio(sbd, &s->iomem_container);
for (i = 0; i < aic->num_ints; i++) {
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);
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);

View File

@ -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"

View File

@ -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);
}

View File

@ -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,

View File

@ -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,

View File

@ -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 enable[ASPEED_INTC_NR_INTS];
uint32_t mask[ASPEED_INTC_NR_INTS];
uint32_t pending[ASPEED_INTC_NR_INTS];
uint32_t *regs;
OrIRQState orgates[ASPEED_INTC_MAX_INPINS];
qemu_irq output_pins[ASPEED_INTC_MAX_OUTPINS];
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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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')

View File

@ -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',

View File

@ -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__':

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()