* [PATCH v2 0/9] Add AST2700 support
@ 2024-03-04 9:29 Jamin Lin via
2024-03-04 9:29 ` [PATCH v2 3/9] aspeed/sdmc: " Jamin Lin via
` (8 more replies)
0 siblings, 9 replies; 24+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:29 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
Changes from v1:
The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC.
Changes from v2:
- replace is_aarch64 with is_bus64bit for sdmc patch review.
- fix incorrect dram size for AST2700
Test steps:
1. Download openbmc image for AST2700 from
https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.00
https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.00/
ast2700-default-obmc.tar.gz
2. untar ast2700-default-obmc.tar.gz
```
tar -xf ast2700-default-obmc.tar.gz
```
3. Run and the contents of scripts as following
IMGDIR=ast2700-default
UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
UBOOT_DTB_ADDR=$((0x400000000 + ${UBOOT_SIZE}))
qemu-system-aarch64 -M ast2700-evb -nographic\
-device loader,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\
-device loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\
-device loader,addr=0x430000000,file=${IMGDIR}/bl31.bin,force-raw=on\
-device loader,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
-device loader,addr=0x430000000,cpu-num=0\
-device loader,addr=0x430000000,cpu-num=1\
-device loader,addr=0x430000000,cpu-num=2\
-device loader,addr=0x430000000,cpu-num=3\
-smp 4\
-drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
-serial mon:stdio\
-snapshot
Known Issue:
1. QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
but not support Shared Peripheral Interrupt (SPI), yet.
Added work around in INTC patch to set GICINT132[18]
which was BMC UART interrupt if it received GICINT132, so users are
able to type any key from keyboard to trigger GICINT132 interrupt
until AST2700 boot into login prompt. It is a temporary solution.
If users encounter boot stck and no booting log,
please type any key from keyboard.
Jamin Lin (9):
aspeed/wdt: Add AST2700 support
aspeed/sli: Add AST2700 support
aspeed/sdmc: Add AST2700 support
aspeed/smc: Add AST2700 support
aspeed/scu: Add AST2700 support
aspeed/intc: Add AST2700 support
aspeed/soc: Add AST2700 support
aspeed: Add an AST2700 eval board
aspeed/soc: fix incorrect dram size for AST2700
hw/arm/aspeed.c | 32 ++
hw/arm/aspeed_ast27x0.c | 554 +++++++++++++++++++++++++++++++
hw/arm/meson.build | 1 +
hw/intc/aspeed_intc.c | 135 ++++++++
hw/intc/meson.build | 1 +
hw/misc/aspeed_scu.c | 306 ++++++++++++++++-
hw/misc/aspeed_sdmc.c | 215 ++++++++++--
hw/misc/aspeed_sli.c | 179 ++++++++++
hw/misc/meson.build | 3 +-
hw/misc/trace-events | 11 +
hw/ssi/aspeed_smc.c | 326 ++++++++++++++++--
hw/ssi/trace-events | 2 +-
hw/watchdog/wdt_aspeed.c | 24 ++
include/hw/arm/aspeed_soc.h | 27 +-
include/hw/intc/aspeed_vic.h | 29 ++
include/hw/misc/aspeed_scu.h | 47 ++-
include/hw/misc/aspeed_sdmc.h | 4 +-
include/hw/misc/aspeed_sli.h | 32 ++
include/hw/ssi/aspeed_smc.h | 1 +
include/hw/watchdog/wdt_aspeed.h | 3 +-
20 files changed, 1880 insertions(+), 52 deletions(-)
create mode 100644 hw/arm/aspeed_ast27x0.c
create mode 100644 hw/intc/aspeed_intc.c
create mode 100644 hw/misc/aspeed_sli.c
create mode 100644 include/hw/misc/aspeed_sli.h
--
2.25.1
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
2024-03-04 9:29 [PATCH v2 0/9] Add AST2700 support Jamin Lin via
@ 2024-03-04 9:29 ` Jamin Lin via
2024-03-04 14:47 ` Cédric Le Goater
2024-03-04 9:29 ` [PATCH v2 4/9] aspeed/smc: " Jamin Lin via
` (7 subsequent siblings)
8 siblings, 1 reply; 24+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:29 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
The SDRAM memory controller(DRAMC) controls the access to external
DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
The DRAM memory controller of AST2700 is not backward compatible
to previous chips such AST2600, AST2500 and AST2400.
Max memory is now 8GiB on the AST2700. Introduce new
aspeed_2700_sdmc and class with read/write operation and
reset handlers.
Define DRAMC necessary protected registers and
unprotected registers for AST2700 and increase
the register set to 0x1000.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/misc/aspeed_sdmc.c | 215 ++++++++++++++++++++++++++++++----
include/hw/misc/aspeed_sdmc.h | 4 +-
2 files changed, 198 insertions(+), 21 deletions(-)
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 64cd1a81dc..63fb7936c4 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -27,6 +27,7 @@
#define PROT_SOFTLOCKED 0x00
#define PROT_KEY_UNLOCK 0xFC600309
+#define PROT_2700_KEY_UNLOCK 0x1688A8A8
#define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
/* Configuration Register */
@@ -54,6 +55,46 @@
#define R_DRAM_TIME (0x8c / 4)
#define R_ECC_ERR_INJECT (0xb4 / 4)
+/* AST2700 Register */
+#define R_2700_PROT (0x00 / 4)
+#define R_INT_STATUS (0x04 / 4)
+#define R_INT_CLEAR (0x08 / 4)
+#define R_INT_MASK (0x0c / 4)
+#define R_MAIN_CONF (0x10 / 4)
+#define R_MAIN_CONTROL (0x14 / 4)
+#define R_MAIN_STATUS (0x18 / 4)
+#define R_ERR_STATUS (0x1c / 4)
+#define R_ECC_FAIL_STATUS (0x78 / 4)
+#define R_ECC_FAIL_ADDR (0x7c / 4)
+#define R_ECC_TESTING_CONTROL (0x80 / 4)
+#define R_PROT_REGION_LOCK_STATUS (0x94 / 4)
+#define R_TEST_FAIL_ADDR (0xd4 / 4)
+#define R_TEST_FAIL_D0 (0xd8 / 4)
+#define R_TEST_FAIL_D1 (0xdc / 4)
+#define R_TEST_FAIL_D2 (0xe0 / 4)
+#define R_TEST_FAIL_D3 (0xe4 / 4)
+#define R_DBG_STATUS (0xf4 / 4)
+#define R_PHY_INTERFACE_STATUS (0xf8 / 4)
+#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4)
+#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4)
+#define R_PORT0_INTERFACE_MONITOR1 (0x244 / 4)
+#define R_PORT0_INTERFACE_MONITOR2 (0x248 / 4)
+#define R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4)
+#define R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4)
+#define R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4)
+#define R_PORT2_INTERFACE_MONITOR0 (0x340 / 4)
+#define R_PORT2_INTERFACE_MONITOR1 (0x344 / 4)
+#define R_PORT2_INTERFACE_MONITOR2 (0x348 / 4)
+#define R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4)
+#define R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4)
+#define R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4)
+#define R_PORT4_INTERFACE_MONITOR0 (0x440 / 4)
+#define R_PORT4_INTERFACE_MONITOR1 (0x444 / 4)
+#define R_PORT4_INTERFACE_MONITOR2 (0x448 / 4)
+#define R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4)
+#define R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4)
+#define R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4)
+
/*
* Configuration register Ox4 (for Aspeed AST2400 SOC)
*
@@ -76,10 +117,6 @@
#define ASPEED_SDMC_VGA_32MB 0x2
#define ASPEED_SDMC_VGA_64MB 0x3
#define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
-#define ASPEED_SDMC_DRAM_64MB 0x0
-#define ASPEED_SDMC_DRAM_128MB 0x1
-#define ASPEED_SDMC_DRAM_256MB 0x2
-#define ASPEED_SDMC_DRAM_512MB 0x3
#define ASPEED_SDMC_READONLY_MASK \
(ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
@@ -100,22 +137,24 @@
#define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs from AST2400 */
#define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs from AST2400 */
-/* DRAM size definitions differs */
-#define ASPEED_SDMC_AST2500_128MB 0x0
-#define ASPEED_SDMC_AST2500_256MB 0x1
-#define ASPEED_SDMC_AST2500_512MB 0x2
-#define ASPEED_SDMC_AST2500_1024MB 0x3
-
-#define ASPEED_SDMC_AST2600_256MB 0x0
-#define ASPEED_SDMC_AST2600_512MB 0x1
-#define ASPEED_SDMC_AST2600_1024MB 0x2
-#define ASPEED_SDMC_AST2600_2048MB 0x3
-
#define ASPEED_SDMC_AST2500_READONLY_MASK \
(ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \
ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
+/*
+ * Main Configuration register Ox10 (for Aspeed AST2700 SOC and higher)
+ *
+ */
+#define ASPEED_SDMC_AST2700_RESERVED 0xFFFF2082 /* 31:16, 13, 7, 1 */
+#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8)
+#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6)
+#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE (1 << 5)
+#define ASPEED_SDMC_AST2700_DRAM_SIZE(x) ((x & 0x7) << 2)
+
+#define ASPEED_SDMC_AST2700_READONLY_MASK \
+ (ASPEED_SDMC_AST2700_RESERVED)
+
static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
{
AspeedSDMCState *s = ASPEED_SDMC(opaque);
@@ -231,7 +270,10 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
AspeedSDMCState *s = ASPEED_SDMC(dev);
AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
- assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
+ if (!asc->is_bus64bit) {
+ assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
+ }
+
s->max_ram_size = asc->max_ram_size;
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
@@ -311,7 +353,8 @@ static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data)
{
if (reg == R_PROT) {
- s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
+ s->regs[reg] =
+ (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
return;
}
@@ -369,7 +412,8 @@ static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data)
{
if (reg == R_PROT) {
- s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
+ s->regs[reg] =
+ (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
return;
}
@@ -449,8 +493,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
}
if (s->regs[R_PROT] == PROT_HARDLOCKED) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n",
- __func__);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked until system reset!\n",
+ __func__);
return;
}
@@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info = {
.class_init = aspeed_2600_sdmc_class_init,
};
+static void aspeed_2700_sdmc_reset(DeviceState *dev)
+{
+ AspeedSDMCState *s = ASPEED_SDMC(dev);
+ AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ /* Set ram size bit and defaults values */
+ s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
+ s->regs[R_2700_PROT] = PROT_UNLOCKED;
+}
+
+static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
+{
+ uint32_t fixed_conf = ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
+ ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
+
+ /* Make sure readonly bits are kept */
+ data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
+
+ return data | fixed_conf;
+}
+
+static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
+ uint32_t data)
+{
+ /* Unprotected registers */
+ switch (reg) {
+ case R_INT_STATUS:
+ case R_INT_CLEAR:
+ case R_INT_MASK:
+ case R_MAIN_STATUS:
+ case R_ERR_STATUS:
+ case R_ECC_FAIL_STATUS:
+ case R_ECC_FAIL_ADDR:
+ case R_PROT_REGION_LOCK_STATUS:
+ case R_TEST_FAIL_ADDR:
+ case R_TEST_FAIL_D0:
+ case R_TEST_FAIL_D1:
+ case R_TEST_FAIL_D2:
+ case R_TEST_FAIL_D3:
+ case R_DBG_STATUS:
+ case R_PHY_INTERFACE_STATUS:
+ case R_GRAPHIC_MEM_BASE_ADDR:
+ case R_PORT0_INTERFACE_MONITOR0:
+ case R_PORT0_INTERFACE_MONITOR1:
+ case R_PORT0_INTERFACE_MONITOR2:
+ case R_PORT1_INTERFACE_MONITOR0:
+ case R_PORT1_INTERFACE_MONITOR1:
+ case R_PORT1_INTERFACE_MONITOR2:
+ case R_PORT2_INTERFACE_MONITOR0:
+ case R_PORT2_INTERFACE_MONITOR1:
+ case R_PORT2_INTERFACE_MONITOR2:
+ case R_PORT3_INTERFACE_MONITOR0:
+ case R_PORT3_INTERFACE_MONITOR1:
+ case R_PORT3_INTERFACE_MONITOR2:
+ case R_PORT4_INTERFACE_MONITOR0:
+ case R_PORT4_INTERFACE_MONITOR1:
+ case R_PORT4_INTERFACE_MONITOR2:
+ case R_PORT5_INTERFACE_MONITOR0:
+ case R_PORT5_INTERFACE_MONITOR1:
+ case R_PORT5_INTERFACE_MONITOR2:
+ s->regs[reg] = data;
+ return;
+ }
+
+ if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked until system reset!\n",
+ __func__);
+ return;
+ }
+
+ if (reg != R_2700_PROT && s->regs[R_2700_PROT] == PROT_SOFTLOCKED) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked! (write to MCR%02x blocked)\n",
+ __func__, reg * 4);
+ return;
+ }
+
+ switch (reg) {
+ case R_2700_PROT:
+ if (data == PROT_2700_KEY_UNLOCK) {
+ data = PROT_UNLOCKED;
+ } else if (data == PROT_KEY_HARDLOCK) {
+ data = PROT_HARDLOCKED;
+ } else {
+ data = PROT_SOFTLOCKED;
+ }
+ break;
+ case R_MAIN_CONF:
+ data = aspeed_2700_sdmc_compute_conf(s, data);
+ break;
+ case R_MAIN_STATUS:
+ /* Will never return 'busy'. */
+ data &= ~PHY_BUSY_STATE;
+ break;
+ default:
+ break;
+ }
+
+ s->regs[reg] = data;
+}
+
+static const uint64_t
+ aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
+ 2048 * MiB, 4096 * MiB, 8192 * MiB, 0};
+
+static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 SDRAM Memory Controller";
+ dc->reset = aspeed_2700_sdmc_reset;
+
+ asc->is_bus64bit = true;
+ asc->max_ram_size = 8 * GiB;
+ asc->compute_conf = aspeed_2700_sdmc_compute_conf;
+ asc->write = aspeed_2700_sdmc_write;
+ asc->valid_ram_sizes = aspeed_2700_ram_sizes;
+}
+
+static const TypeInfo aspeed_2700_sdmc_info = {
+ .name = TYPE_ASPEED_2700_SDMC,
+ .parent = TYPE_ASPEED_SDMC,
+ .class_init = aspeed_2700_sdmc_class_init,
+};
+
static void aspeed_sdmc_register_types(void)
{
type_register_static(&aspeed_sdmc_info);
type_register_static(&aspeed_2400_sdmc_info);
type_register_static(&aspeed_2500_sdmc_info);
type_register_static(&aspeed_2600_sdmc_info);
+ type_register_static(&aspeed_2700_sdmc_info);
}
type_init(aspeed_sdmc_register_types);
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index ec2d59a14f..6df2f0a3b7 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
#define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
#define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
#define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
+#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
/*
* SDMC has 174 documented registers. In addition the u-boot device tree
@@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
* time, and the other is in the DDR-PHY IP which is used during DDR-PHY
* training.
*/
-#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
+#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
struct AspeedSDMCState {
/*< private >*/
@@ -51,6 +52,7 @@ struct AspeedSDMCClass {
const uint64_t *valid_ram_sizes;
uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
+ bool is_bus64bit;
};
#endif /* ASPEED_SDMC_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 4/9] aspeed/smc: Add AST2700 support
2024-03-04 9:29 [PATCH v2 0/9] Add AST2700 support Jamin Lin via
2024-03-04 9:29 ` [PATCH v2 3/9] aspeed/sdmc: " Jamin Lin via
@ 2024-03-04 9:29 ` Jamin Lin via
2024-03-04 15:19 ` Cédric Le Goater
2024-03-04 9:29 ` [PATCH v2 5/9] aspeed/scu: " Jamin Lin via
` (6 subsequent siblings)
8 siblings, 1 reply; 24+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:29 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 fmc/spi controller's address decoding unit is 64KB
and only bits [31:16] are used for decoding. Introduce seg_to_reg
and reg_to_seg handlers for ast2700 fmc/spi controller.
In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler.
AST2700 support the maximum dram size is 8GiB.
Update dma_rw function and trace-event to support 64 bits dram
address. DMA length is from 1 byte to 32MB for AST2700, AST2600 and AST10x0
and DMA length is from 4 bytes to 32MB for AST2500.
In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
data for AST2700, AST2600 and AST10x0 and 4 bytes data for AST2500.
To support all ASPEED SOCs, adds dma_start_length parameter to store
the start length and update DMA_LENGTH mask to "1FFFFFF" to fix dma moving
incorrect data length issue.
Currently, dma_rw function only supports length 4 bytes aligned.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/ssi/aspeed_smc.c | 326 +++++++++++++++++++++++++++++++++---
hw/ssi/trace-events | 2 +-
include/hw/ssi/aspeed_smc.h | 1 +
3 files changed, 309 insertions(+), 20 deletions(-)
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 3c93936fd1..73121edf2b 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -131,6 +131,9 @@
#define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */
#define FMC_WDT2_CTRL_EN BIT(0)
+/* DMA DRAM Side Address High Part (AST2700) */
+#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4)
+
/* DMA Control/Status Register */
#define R_DMA_CTRL (0x80 / 4)
#define DMA_CTRL_REQUEST (1 << 31)
@@ -177,13 +180,18 @@
* DMA flash addresses should be 4 bytes aligned and the valid address
* range is 0x20000000 - 0x2FFFFFFF.
*
- * DMA length is from 4 bytes to 32MB
+ * DMA length is from 4 bytes to 32MB (AST2500)
* 0: 4 bytes
* 0x7FFFFF: 32M bytes
+ *
+ * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700)
+ * 0: 1 byte
+ * 0x1FFFFFF: 32M bytes
*/
#define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask)
+#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf)
#define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask)
-#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
+#define DMA_LENGTH(val) ((val) & 0x01FFFFFF)
/* Flash opcodes. */
#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
@@ -202,6 +210,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
#define ASPEED_SMC_FEATURE_DMA 0x1
#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
#define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
+#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
{
@@ -213,6 +222,11 @@ static inline bool aspeed_smc_has_wdt_control(const AspeedSMCClass *asc)
return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
}
+static inline bool aspeed_smc_has_dma_dram_addr_high(const AspeedSMCClass *asc)
+{
+ return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
+}
+
#define aspeed_smc_error(fmt, ...) \
qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
@@ -655,7 +669,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 1,
- .max_access_size = 4,
+ .max_access_size = 8,
},
};
@@ -734,6 +748,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
(aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) ||
+ (aspeed_smc_has_dma(asc) &&
+ aspeed_smc_has_dma_dram_addr_high(asc) &&
+ addr == R_DMA_DRAM_ADDR_HIGH) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
(addr >= R_SEG_ADDR0 &&
@@ -840,8 +857,11 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
*/
static void aspeed_smc_dma_checksum(AspeedSMCState *s)
{
+ AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
MemTxResult result;
+ uint32_t dma_len;
uint32_t data;
+ uint32_t extra;
if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
aspeed_smc_error("invalid direction for DMA checksum");
@@ -852,7 +872,14 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
aspeed_smc_dma_calibration(s);
}
- while (s->regs[R_DMA_LEN]) {
+ dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
+ /* dma length 4 bytes aligned */
+ extra = dma_len % 4;
+ if (extra != 0) {
+ dma_len += 4 - extra;
+ }
+
+ while (dma_len) {
data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) {
@@ -868,7 +895,8 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
*/
s->regs[R_DMA_CHECKSUM] += data;
s->regs[R_DMA_FLASH_ADDR] += 4;
- s->regs[R_DMA_LEN] -= 4;
+ dma_len -= 4;
+ s->regs[R_DMA_LEN] = dma_len;
}
if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
@@ -879,21 +907,44 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
static void aspeed_smc_dma_rw(AspeedSMCState *s)
{
+ AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+ uint64_t dram_addr_high;
+ uint64_t dma_dram_addr;
+ uint64_t dram_addr;
MemTxResult result;
+ uint32_t dma_len;
uint32_t data;
+ uint32_t extra;
+
+ if (aspeed_smc_has_dma_dram_addr_high(asc)) {
+ dram_addr_high = s->regs[R_DMA_DRAM_ADDR_HIGH];
+ dram_addr_high <<= 32;
+ dma_dram_addr = dram_addr_high | s->regs[R_DMA_DRAM_ADDR];
+ dram_addr = dma_dram_addr - s->dram_mr->container->addr;
+ } else {
+ dma_dram_addr = s->regs[R_DMA_DRAM_ADDR];
+ dram_addr = dma_dram_addr;
+ }
+
+ dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
+ /* dma length 4 bytes aligned */
+ extra = dma_len % 4;
+ if (extra != 0) {
+ dma_len += 4 - extra;
+ }
trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
"write" : "read",
s->regs[R_DMA_FLASH_ADDR],
- s->regs[R_DMA_DRAM_ADDR],
- s->regs[R_DMA_LEN]);
- while (s->regs[R_DMA_LEN]) {
+ dram_addr,
+ dma_len);
+
+ while (dma_len) {
if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
- data = address_space_ldl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
+ data = address_space_ldl_le(&s->dram_as, dram_addr,
MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) {
- aspeed_smc_error("DRAM read failed @%08x",
- s->regs[R_DMA_DRAM_ADDR]);
+ aspeed_smc_error("DRAM read failed @%" PRIx64, dram_addr);
return;
}
@@ -913,11 +964,10 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
return;
}
- address_space_stl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
+ address_space_stl_le(&s->dram_as, dram_addr,
data, MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) {
- aspeed_smc_error("DRAM write failed @%08x",
- s->regs[R_DMA_DRAM_ADDR]);
+ aspeed_smc_error("DRAM write failed @%" PRIx64, dram_addr);
return;
}
}
@@ -926,10 +976,18 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
* When the DMA is on-going, the DMA registers are updated
* with the current working addresses and length.
*/
+ dram_addr += 4;
+ dma_dram_addr += 4;
+ if (aspeed_smc_has_dma_dram_addr_high(asc)) {
+ dram_addr_high = dma_dram_addr >> 32;
+ s->regs[R_DMA_DRAM_ADDR_HIGH] = dram_addr_high;
+ }
+
+ s->regs[R_DMA_DRAM_ADDR] = dma_dram_addr & 0xffffffff;
s->regs[R_DMA_FLASH_ADDR] += 4;
- s->regs[R_DMA_DRAM_ADDR] += 4;
- s->regs[R_DMA_LEN] -= 4;
s->regs[R_DMA_CHECKSUM] += data;
+ dma_len -= 4;
+ s->regs[R_DMA_LEN] = dma_len;
}
}
@@ -1079,6 +1137,10 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
} else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN &&
aspeed_smc_dma_granted(s)) {
s->regs[addr] = DMA_LENGTH(value);
+ } else if (aspeed_smc_has_dma(asc) &&
+ aspeed_smc_has_dma_dram_addr_high(asc) &&
+ addr == R_DMA_DRAM_ADDR_HIGH) {
+ s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
} else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr);
@@ -1372,6 +1434,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x1FFFFFFC;
+ asc->dma_start_length = 4;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment;
@@ -1439,7 +1502,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
- dc->desc = "Aspeed 2600 FMC Controller";
+ dc->desc = "Aspeed 2500 FMC Controller";
asc->r_conf = R_CONF;
asc->r_ce_ctrl = R_CE_CTRL;
asc->r_ctrl0 = R_CTRL0;
@@ -1455,6 +1518,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC;
+ asc->dma_start_length = 4;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment;
@@ -1477,7 +1541,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
- dc->desc = "Aspeed 2600 SPI1 Controller";
+ dc->desc = "Aspeed 2500 SPI1 Controller";
asc->r_conf = R_CONF;
asc->r_ce_ctrl = R_CE_CTRL;
asc->r_ctrl0 = R_CTRL0;
@@ -1512,7 +1576,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
- dc->desc = "Aspeed 2600 SPI2 Controller";
+ dc->desc = "Aspeed 2500 SPI2 Controller";
asc->r_conf = R_CONF;
asc->r_ce_ctrl = R_CE_CTRL;
asc->r_ctrl0 = R_CTRL0;
@@ -1611,6 +1675,7 @@ static void aspeed_2600_fmc_class_init(ObjectClass *klass, void *data)
ASPEED_SMC_FEATURE_WDT_CONTROL;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC;
+ asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
@@ -1649,6 +1714,7 @@ static void aspeed_2600_spi1_class_init(ObjectClass *klass, void *data)
ASPEED_SMC_FEATURE_DMA_GRANT;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC;
+ asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
@@ -1688,6 +1754,7 @@ static void aspeed_2600_spi2_class_init(ObjectClass *klass, void *data)
ASPEED_SMC_FEATURE_DMA_GRANT;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC;
+ asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
@@ -1769,6 +1836,7 @@ static void aspeed_1030_fmc_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x000BFFFC;
+ asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_1030_smc_segment_to_reg;
asc->reg_to_segment = aspeed_1030_smc_reg_to_segment;
@@ -1806,6 +1874,7 @@ static void aspeed_1030_spi1_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x000BFFFC;
+ asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
@@ -1842,6 +1911,7 @@ static void aspeed_1030_spi2_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x000BFFFC;
+ asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
@@ -1854,6 +1924,220 @@ static const TypeInfo aspeed_1030_spi2_info = {
.class_init = aspeed_1030_spi2_class_init,
};
+/*
+ * The FMC Segment Registers of the AST2700 have a 64KB unit.
+ * Only bits [31:16] are used for decoding.
+ */
+#define AST2700_SEG_ADDR_MASK 0xffff0000
+
+static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState *s,
+ const AspeedSegments *seg)
+{
+ uint32_t reg = 0;
+
+ /* Disabled segments have a nil register */
+ if (!seg->size) {
+ return 0;
+ }
+
+ reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset */
+ reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /* end offset */
+ return reg;
+}
+
+static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s,
+ uint32_t reg, AspeedSegments *seg)
+{
+ uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK;
+ uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK;
+ AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+
+ if (reg) {
+ seg->addr = asc->flash_window_base + start_offset;
+ seg->size = end_offset + (64 * KiB) - start_offset;
+ } else {
+ seg->addr = asc->flash_window_base;
+ seg->size = 0;
+ }
+}
+
+static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = {
+ [R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 |
+ CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1),
+ [R_CE_CTRL] = 0x0000aa00,
+ [R_CTRL0] = 0x406b0641,
+ [R_CTRL1] = 0x00000400,
+ [R_CTRL2] = 0x00000400,
+ [R_CTRL3] = 0x00000400,
+ [R_SEG_ADDR0] = 0x08000000,
+ [R_SEG_ADDR1] = 0x10000800,
+ [R_SEG_ADDR2] = 0x00000000,
+ [R_SEG_ADDR3] = 0x00000000,
+ [R_DUMMY_DATA] = 0x00010000,
+ [R_DMA_DRAM_ADDR_HIGH] = 0x00000000,
+ [R_TIMINGS] = 0x007b0000,
+};
+
+static const AspeedSegments aspeed_2700_fmc_segments[] = {
+ { 0x0, 128 * MiB }, /* start address is readonly */
+ { 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
+ { 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
+ { 0x0, 0 }, /* disabled */
+};
+
+static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
+
+ dc->desc = "Aspeed 2700 FMC Controller";
+ asc->r_conf = R_CONF;
+ asc->r_ce_ctrl = R_CE_CTRL;
+ asc->r_ctrl0 = R_CTRL0;
+ asc->r_timings = R_TIMINGS;
+ asc->nregs_timings = 3;
+ asc->conf_enable_w0 = CONF_ENABLE_W0;
+ asc->cs_num_max = 3;
+ asc->segments = aspeed_2700_fmc_segments;
+ asc->segment_addr_mask = 0xffffffff;
+ asc->resets = aspeed_2700_fmc_resets;
+ asc->flash_window_base = 0x100000000;
+ asc->flash_window_size = 1 * GiB;
+ asc->features = ASPEED_SMC_FEATURE_DMA |
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ asc->dma_flash_mask = 0x2FFFFFFC;
+ asc->dma_dram_mask = 0xFFFFFFFC;
+ asc->dma_start_length = 1;
+ asc->nregs = ASPEED_SMC_R_MAX;
+ asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
+ asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
+ asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+}
+
+static const TypeInfo aspeed_2700_fmc_info = {
+ .name = "aspeed.fmc-ast2700",
+ .parent = TYPE_ASPEED_SMC,
+ .class_init = aspeed_2700_fmc_class_init,
+};
+
+static const AspeedSegments aspeed_2700_spi0_segments[] = {
+ { 0x0, 128 * MiB }, /* start address is readonly */
+ { 128 * MiB, 128 * MiB }, /* start address is readonly */
+ { 0x0, 0 }, /* disabled */
+};
+
+static void aspeed_2700_spi0_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
+
+ dc->desc = "Aspeed 2700 SPI0 Controller";
+ asc->r_conf = R_CONF;
+ asc->r_ce_ctrl = R_CE_CTRL;
+ asc->r_ctrl0 = R_CTRL0;
+ asc->r_timings = R_TIMINGS;
+ asc->nregs_timings = 2;
+ asc->conf_enable_w0 = CONF_ENABLE_W0;
+ asc->cs_num_max = 2;
+ asc->segments = aspeed_2700_spi0_segments;
+ asc->segment_addr_mask = 0xffffffff;
+ asc->flash_window_base = 0x180000000;
+ asc->flash_window_size = 1 * GiB;
+ asc->features = ASPEED_SMC_FEATURE_DMA |
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ asc->dma_flash_mask = 0x2FFFFFFC;
+ asc->dma_dram_mask = 0xFFFFFFFC;
+ asc->dma_start_length = 1;
+ asc->nregs = ASPEED_SMC_R_MAX;
+ asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
+ asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
+ asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+}
+
+static const TypeInfo aspeed_2700_spi0_info = {
+ .name = "aspeed.spi0-ast2700",
+ .parent = TYPE_ASPEED_SMC,
+ .class_init = aspeed_2700_spi0_class_init,
+};
+
+static const AspeedSegments aspeed_2700_spi1_segments[] = {
+ { 0x0, 128 * MiB }, /* start address is readonly */
+ { 0x0, 0 }, /* disabled */
+};
+
+static void aspeed_2700_spi1_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
+
+ dc->desc = "Aspeed 2700 SPI1 Controller";
+ asc->r_conf = R_CONF;
+ asc->r_ce_ctrl = R_CE_CTRL;
+ asc->r_ctrl0 = R_CTRL0;
+ asc->r_timings = R_TIMINGS;
+ asc->nregs_timings = 2;
+ asc->conf_enable_w0 = CONF_ENABLE_W0;
+ asc->cs_num_max = 2;
+ asc->segments = aspeed_2700_spi1_segments;
+ asc->segment_addr_mask = 0xffffffff;
+ asc->flash_window_base = 0x200000000;
+ asc->flash_window_size = 1 * GiB;
+ asc->features = ASPEED_SMC_FEATURE_DMA |
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ asc->dma_flash_mask = 0x2FFFFFFC;
+ asc->dma_dram_mask = 0xFFFFFFFC;
+ asc->dma_start_length = 1;
+ asc->nregs = ASPEED_SMC_R_MAX;
+ asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
+ asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
+ asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+}
+
+static const TypeInfo aspeed_2700_spi1_info = {
+ .name = "aspeed.spi1-ast2700",
+ .parent = TYPE_ASPEED_SMC,
+ .class_init = aspeed_2700_spi1_class_init,
+};
+
+static const AspeedSegments aspeed_2700_spi2_segments[] = {
+ { 0x0, 128 * MiB }, /* start address is readonly */
+ { 0x0, 0 }, /* disabled */
+};
+
+static void aspeed_2700_spi2_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
+
+ dc->desc = "Aspeed 2700 SPI2 Controller";
+ asc->r_conf = R_CONF;
+ asc->r_ce_ctrl = R_CE_CTRL;
+ asc->r_ctrl0 = R_CTRL0;
+ asc->r_timings = R_TIMINGS;
+ asc->nregs_timings = 2;
+ asc->conf_enable_w0 = CONF_ENABLE_W0;
+ asc->cs_num_max = 2;
+ asc->segments = aspeed_2700_spi2_segments;
+ asc->segment_addr_mask = 0xffffffff;
+ asc->flash_window_base = 0x280000000;
+ asc->flash_window_size = 1 * GiB;
+ asc->features = ASPEED_SMC_FEATURE_DMA |
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ asc->dma_flash_mask = 0x0FFFFFFC;
+ asc->dma_dram_mask = 0xFFFFFFFC;
+ asc->dma_start_length = 1;
+ asc->nregs = ASPEED_SMC_R_MAX;
+ asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
+ asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
+ asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+}
+
+static const TypeInfo aspeed_2700_spi2_info = {
+ .name = "aspeed.spi2-ast2700",
+ .parent = TYPE_ASPEED_SMC,
+ .class_init = aspeed_2700_spi2_class_init,
+};
+
static void aspeed_smc_register_types(void)
{
type_register_static(&aspeed_smc_flash_info);
@@ -1870,6 +2154,10 @@ static void aspeed_smc_register_types(void)
type_register_static(&aspeed_1030_fmc_info);
type_register_static(&aspeed_1030_spi1_info);
type_register_static(&aspeed_1030_spi2_info);
+ type_register_static(&aspeed_2700_fmc_info);
+ type_register_static(&aspeed_2700_spi0_info);
+ type_register_static(&aspeed_2700_spi1_info);
+ type_register_static(&aspeed_2700_spi2_info);
}
type_init(aspeed_smc_register_types)
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
index 2d5bd2b83d..7b5ad6a939 100644
--- a/hw/ssi/trace-events
+++ b/hw/ssi/trace-events
@@ -6,7 +6,7 @@ aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x d
aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
-aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
+aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint64_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%" PRIx64 " size:0x%08x"
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 8e1dda556b..f359ed22cc 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -106,6 +106,7 @@ struct AspeedSMCClass {
uint32_t features;
hwaddr dma_flash_mask;
hwaddr dma_dram_mask;
+ uint32_t dma_start_length;
uint32_t nregs;
uint32_t (*segment_to_reg)(const AspeedSMCState *s,
const AspeedSegments *seg);
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 5/9] aspeed/scu: Add AST2700 support
2024-03-04 9:29 [PATCH v2 0/9] Add AST2700 support Jamin Lin via
2024-03-04 9:29 ` [PATCH v2 3/9] aspeed/sdmc: " Jamin Lin via
2024-03-04 9:29 ` [PATCH v2 4/9] aspeed/smc: " Jamin Lin via
@ 2024-03-04 9:29 ` Jamin Lin via
2024-03-04 15:37 ` Cédric Le Goater
2024-03-04 9:29 ` [PATCH v2 6/9] aspeed/intc: " Jamin Lin via
` (5 subsequent siblings)
8 siblings, 1 reply; 24+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:29 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 have two SCU controllers which are SCU and SCUIO.
Both SCU and SCUIO registers are not compatible previous SOCs
, introduces new registers and adds ast2700 scu, sucio class init handler.
The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
the pclk divider selection of SCU is defined in SCU280[25:23].
Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
and trace-event for AST2700 SCU and SCUIO.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/misc/aspeed_scu.c | 306 ++++++++++++++++++++++++++++++++++-
hw/misc/trace-events | 4 +
include/hw/misc/aspeed_scu.h | 47 +++++-
3 files changed, 351 insertions(+), 6 deletions(-)
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 1ac04b6cb0..eb38ea8e19 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -134,6 +134,48 @@
#define AST2600_CLK TO_REG(0x40)
+#define AST2700_SILICON_REV TO_REG(0x00)
+#define AST2700_HW_STRAP1 TO_REG(0x10)
+#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
+#define AST2700_HW_STRAP1_LOCK TO_REG(0x20)
+#define AST2700_HW_STRAP1_SEC1 TO_REG(0x24)
+#define AST2700_HW_STRAP1_SEC2 TO_REG(0x28)
+#define AST2700_HW_STRAP1_SEC3 TO_REG(0x2C)
+
+#define AST2700_SCU_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCU_HPLL_PARAM TO_REG(0x300)
+#define AST2700_SCU_HPLL_EXT_PARAM TO_REG(0x304)
+#define AST2700_SCU_DPLL_PARAM TO_REG(0x308)
+#define AST2700_SCU_DPLL_EXT_PARAM TO_REG(0x30c)
+#define AST2700_SCU_MPLL_PARAM TO_REG(0x310)
+#define AST2700_SCU_MPLL_EXT_PARAM TO_REG(0x314)
+#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
+#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
+#define AST2700_SCU_CRT1CLK_PARAM TO_REG(0x340)
+#define AST2700_SCU_CRT2CLK_PARAM TO_REG(0x350)
+#define AST2700_SCU_MPHYCLK_PARAM TO_REG(0x360)
+#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_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
+#define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
+#define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260)
+#define AST2700_SCUIO_CLK_STOP_CLR_2 TO_REG(0x264)
+#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
+#define AST2700_SCUIO_HPLL_PARAM TO_REG(0x300)
+#define AST2700_SCUIO_HPLL_EXT_PARAM TO_REG(0x304)
+#define AST2700_SCUIO_APLL_PARAM TO_REG(0x310)
+#define AST2700_SCUIO_APLL_EXT_PARAM TO_REG(0x314)
+#define AST2700_SCUIO_DPLL_PARAM TO_REG(0x320)
+#define AST2700_SCUIO_DPLL_EXT_PARAM TO_REG(0x324)
+#define AST2700_SCUIO_DPLL_PARAM_READ TO_REG(0x328)
+#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
+#define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
+#define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
+#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+
#define SCU_IO_REGION_SIZE 0x1000
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
@@ -244,6 +286,25 @@ static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
/ asc->apb_divider;
}
+static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
+{
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+ uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
+
+ return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
+ / asc->apb_divider;
+}
+
+static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
+{
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+ uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
+
+ return hpll /
+ (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
+ / asc->apb_divider;
+}
+
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
{
AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
switch (reg) {
case RNG_DATA:
- /* On hardware, RNG_DATA works regardless of
+ /*
+ * On hardware, RNG_DATA works regardless of
* the state of the enable bit in RNG_CTRL
*/
s->regs[RNG_DATA] = aspeed_scu_get_random();
@@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
AST2600_A3_SILICON_REV,
AST1030_A0_SILICON_REV,
AST1030_A1_SILICON_REV,
+ AST2700_A0_SILICON_REV,
+ AST2720_A0_SILICON_REV,
+ AST2750_A0_SILICON_REV,
};
bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
.class_init = aspeed_2600_scu_class_init,
};
+static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ AspeedSCUState *s = ASPEED_SCU(opaque);
+ int reg = TO_REG(offset);
+
+ if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ return 0;
+ }
+
+ switch (reg) {
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ }
+
+ trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
+ return s->regs[reg];
+}
+
+static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
+ uint64_t data64, unsigned size)
+{
+ AspeedSCUState *s = ASPEED_SCU(opaque);
+ int reg = TO_REG(offset);
+ /* Truncate here so bitwise operations below behave as expected */
+ uint32_t data = data64;
+
+ if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ return;
+ }
+
+ trace_aspeed_ast2700_scu_write(offset, size, data);
+
+ switch (reg) {
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Unhandeled write at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+
+ s->regs[reg] = data;
+}
+
+static const MemoryRegionOps aspeed_ast2700_scu_ops = {
+ .read = aspeed_ast2700_scu_read,
+ .write = aspeed_ast2700_scu_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 8,
+ .valid.unaligned = false,
+};
+
+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,
+ [AST2700_HW_STRAP1_SEC2] = 0x00000000,
+ [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
+ [AST2700_SCU_HPLL_PARAM] = 0x0000009f,
+ [AST2700_SCU_HPLL_EXT_PARAM] = 0x8000004f,
+ [AST2700_SCU_DPLL_PARAM] = 0x0080009f,
+ [AST2700_SCU_DPLL_EXT_PARAM] = 0x8000004f,
+ [AST2700_SCU_MPLL_PARAM] = 0x00000040,
+ [AST2700_SCU_MPLL_EXT_PARAM] = 0x80000000,
+ [AST2700_SCU_D1CLK_PARAM] = 0x00050002,
+ [AST2700_SCU_D2CLK_PARAM] = 0x00050002,
+ [AST2700_SCU_CRT1CLK_PARAM] = 0x00050002,
+ [AST2700_SCU_CRT2CLK_PARAM] = 0x00050002,
+ [AST2700_SCU_MPHYCLK_PARAM] = 0x0000004c,
+ [AST2700_SCU_FREQ_CNTR] = 0x000375eb,
+ [AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
+ [AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
+};
+
+static void aspeed_ast2700_scu_reset(DeviceState *dev)
+{
+ AspeedSCUState *s = ASPEED_SCU(dev);
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
+
+ memcpy(s->regs, asc->resets, asc->nr_regs * 4);
+}
+
+static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 System Control Unit";
+ dc->reset = aspeed_ast2700_scu_reset;
+ asc->resets = ast2700_a0_resets;
+ asc->calc_hpll = aspeed_2600_scu_calc_hpll;
+ asc->get_apb = aspeed_2700_scu_get_apb_freq;
+ asc->apb_divider = 4;
+ asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
+ asc->clkin_25Mhz = true;
+ asc->ops = &aspeed_ast2700_scu_ops;
+}
+
+static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ AspeedSCUState *s = ASPEED_SCU(opaque);
+ int reg = TO_REG(offset);
+ if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ return 0;
+ }
+
+ switch (reg) {
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ }
+
+ trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
+ return s->regs[reg];
+}
+
+static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
+ uint64_t data64, unsigned size)
+{
+ AspeedSCUState *s = ASPEED_SCU(opaque);
+ int reg = TO_REG(offset);
+ /* Truncate here so bitwise operations below behave as expected */
+ uint32_t data = data64;
+ bool updated = false;
+
+ if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ return;
+ }
+
+ trace_aspeed_ast2700_scuio_write(offset, size, data);
+
+ switch (reg) {
+ case AST2700_SCUIO_CLK_STOP_CTL_1:
+ case AST2700_SCUIO_CLK_STOP_CTL_2:
+ s->regs[reg] |= data;
+ updated = true;
+ break;
+ case AST2700_SCUIO_CLK_STOP_CLR_1:
+ case AST2700_SCUIO_CLK_STOP_CLR_2:
+ s->regs[reg - 1] ^= data;
+ updated = true;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Unhandeled write at offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+
+ if (!updated) {
+ s->regs[reg] = data;
+ }
+}
+
+static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
+ .read = aspeed_ast2700_scuio_read,
+ .write = aspeed_ast2700_scuio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 8,
+ .valid.unaligned = false,
+};
+
+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,
+ [AST2700_HW_STRAP1_SEC2] = 0x00000000,
+ [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
+ [AST2700_SCUIO_CLK_STOP_CTL_1] = 0xffff8400,
+ [AST2700_SCUIO_CLK_STOP_CTL_2] = 0x00005f30,
+ [AST2700_SCUIO_CLK_SEL_1] = 0x86900000,
+ [AST2700_SCUIO_CLK_SEL_2] = 0x00400000,
+ [AST2700_SCUIO_HPLL_PARAM] = 0x10000027,
+ [AST2700_SCUIO_HPLL_EXT_PARAM] = 0x80000014,
+ [AST2700_SCUIO_APLL_PARAM] = 0x1000001f,
+ [AST2700_SCUIO_APLL_EXT_PARAM] = 0x8000000f,
+ [AST2700_SCUIO_DPLL_PARAM] = 0x106e42ce,
+ [AST2700_SCUIO_DPLL_EXT_PARAM] = 0x80000167,
+ [AST2700_SCUIO_DPLL_PARAM_READ] = 0x106e42ce,
+ [AST2700_SCUIO_DPLL_EXT_PARAM_READ] = 0x80000167,
+ [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
+ [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
+ [AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2,
+};
+
+static void aspeed_2700_scuio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 System Control Unit I/O";
+ dc->reset = aspeed_ast2700_scu_reset;
+ asc->resets = ast2700_a0_resets_io;
+ asc->calc_hpll = aspeed_2600_scu_calc_hpll;
+ asc->get_apb = aspeed_2700_scuio_get_apb_freq;
+ asc->apb_divider = 2;
+ asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
+ asc->clkin_25Mhz = true;
+ asc->ops = &aspeed_ast2700_scuio_ops;
+}
+
+static const TypeInfo aspeed_2700_scu_info = {
+ .name = TYPE_ASPEED_2700_SCU,
+ .parent = TYPE_ASPEED_SCU,
+ .instance_size = sizeof(AspeedSCUState),
+ .class_init = aspeed_2700_scu_class_init,
+};
+
+static const TypeInfo aspeed_2700_scuio_info = {
+ .name = TYPE_ASPEED_2700_SCUIO,
+ .parent = TYPE_ASPEED_SCU,
+ .instance_size = sizeof(AspeedSCUState),
+ .class_init = aspeed_2700_scuio_class_init,
+};
+
static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
[AST2600_SYS_RST_CTRL] = 0xFFC3FED8,
[AST2600_SYS_RST_CTRL2] = 0x09FFFFFC,
@@ -841,6 +1143,8 @@ static void aspeed_scu_register_types(void)
type_register_static(&aspeed_2500_scu_info);
type_register_static(&aspeed_2600_scu_info);
type_register_static(&aspeed_1030_scu_info);
+ type_register_static(&aspeed_2700_scu_info);
+ type_register_static(&aspeed_2700_scuio_info);
}
type_init(aspeed_scu_register_types);
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 07010a7ea6..5e5cd77420 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -93,6 +93,10 @@ slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED 0x%04x"
# aspeed_scu.c
aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_scu_read(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_ast2700_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_ast2700_scu_read(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_ast2700_scuio_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_ast2700_scuio_read(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
# mps2-scc.c
mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index 7cb6018dbc..58db28db45 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -19,10 +19,13 @@ OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEED_SCU)
#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
#define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600"
+#define TYPE_ASPEED_2700_SCU TYPE_ASPEED_SCU "-ast2700"
+#define TYPE_ASPEED_2700_SCUIO TYPE_ASPEED_SCU "io" "-ast2700"
#define TYPE_ASPEED_1030_SCU TYPE_ASPEED_SCU "-ast1030"
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
#define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
+#define ASPEED_AST2700_SCU_NR_REGS (0xE20 >> 2)
struct AspeedSCUState {
/*< private >*/
@@ -31,7 +34,7 @@ struct AspeedSCUState {
/*< public >*/
MemoryRegion iomem;
- uint32_t regs[ASPEED_AST2600_SCU_NR_REGS];
+ uint32_t regs[ASPEED_AST2700_SCU_NR_REGS];
uint32_t silicon_rev;
uint32_t hw_strap1;
uint32_t hw_strap2;
@@ -48,6 +51,9 @@ struct AspeedSCUState {
#define AST2600_A3_SILICON_REV 0x05030303U
#define AST1030_A0_SILICON_REV 0x80000000U
#define AST1030_A1_SILICON_REV 0x80010000U
+#define AST2700_A0_SILICON_REV 0x06000103U
+#define AST2720_A0_SILICON_REV 0x06000203U
+#define AST2750_A0_SILICON_REV 0x06000003U
#define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04)
@@ -87,7 +93,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
* 1. 2012/12/29 Ryan Chen Create
*/
-/* SCU08 Clock Selection Register
+/*
+ * SCU08 Clock Selection Register
*
* 31 Enable Video Engine clock dynamic slow down
* 30:28 Video Engine clock slow down setting
@@ -109,7 +116,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
*/
#define SCU_CLK_GET_PCLK_DIV(x) (((x) >> 23) & 0x7)
-/* SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
+/*
+ * SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
*
* 18 H-PLL parameter selection
* 0: Select H-PLL by strapping resistors
@@ -127,7 +135,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
#define SCU_AST2400_H_PLL_BYPASS_EN (0x1 << 17)
#define SCU_AST2400_H_PLL_OFF (0x1 << 16)
-/* SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
+/*
+ * SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
*
* 21 Enable H-PLL reset
* 20 Enable H-PLL bypass mode
@@ -144,7 +153,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
#define SCU_H_PLL_BYPASS_EN (0x1 << 20)
#define SCU_H_PLL_OFF (0x1 << 19)
-/* SCU70 Hardware Strapping Register definition (for Aspeed AST2400 SOC)
+/*
+ * SCU70 Hardware Strapping Register definition (for Aspeed AST2400 SOC)
*
* 31:29 Software defined strapping registers
* 28:27 DRAM size setting (for VGA driver use)
@@ -361,4 +371,31 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
*/
#define SCU_AST1030_CLK_GET_PCLK_DIV(x) (((x) >> 8) & 0xf)
+/*
+ * SCU280 Clock Selection 1 Register (for Aspeed AST2700 SCUIO)
+ *
+ * 31:29 MHCLK_DIV
+ * 28 Reserved
+ * 27:25 RGMIICLK_DIV
+ * 24 Reserved
+ * 23:21 RMIICLK_DIV
+ * 20:18 PCLK_DIV
+ * 17:14 SDCLK_DIV
+ * 13 SDCLK_SEL
+ * 12 UART13CLK_SEL
+ * 11 UART12CLK_SEL
+ * 10 UART11CLK_SEL
+ * 9 UART10CLK_SEL
+ * 8 UART9CLK_SEL
+ * 7 UART8CLK_SEL
+ * 6 UART7CLK_SEL
+ * 5 UART6CLK_SEL
+ * 4 UARTDBCLK_SEL
+ * 3 UART4CLK_SEL
+ * 2 UART3CLK_SEL
+ * 1 UART2CLK_SEL
+ * 0 UART1CLK_SEL
+ */
+#define SCUIO_AST2700_CLK_GET_PCLK_DIV(x) (((x) >> 18) & 0x7)
+
#endif /* ASPEED_SCU_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 6/9] aspeed/intc: Add AST2700 support
2024-03-04 9:29 [PATCH v2 0/9] Add AST2700 support Jamin Lin via
` (2 preceding siblings ...)
2024-03-04 9:29 ` [PATCH v2 5/9] aspeed/scu: " Jamin Lin via
@ 2024-03-04 9:29 ` Jamin Lin via
[not found] ` <20240304092934.1953198-2-jamin_lin@aspeedtech.com>
` (4 subsequent siblings)
8 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:29 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 interrupt controller(INTC) provides hardware interrupt interfaces
to interrupt of processors PSP, SSP and TSP. In INTC, each interrupt of
INT 128 to INT136 combines 32 interrupts.
Introduce a new aspeed_intc class with instance_init and realize handlers.
QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
but not support Shared Peripheral Interrupt (SPI), yet.
This patch added work around to set GICINT132[18] which was BMC UART interrupt
if it received GICINT132, so users are able to type any key from keyboard to
trigger GICINT132 interrupt until AST2700 boot into login prompt.
It is a temporary solution.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/intc/aspeed_intc.c | 135 +++++++++++++++++++++++++++++++++++
hw/intc/meson.build | 1 +
include/hw/intc/aspeed_vic.h | 29 ++++++++
3 files changed, 165 insertions(+)
create mode 100644 hw/intc/aspeed_intc.c
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
new file mode 100644
index 0000000000..851d43363b
--- /dev/null
+++ b/hw/intc/aspeed_intc.c
@@ -0,0 +1,135 @@
+/*
+ * ASPEED INTC Controller
+ *
+ * Copyright (C) 2024 ASPEED Technology Inc.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/intc/aspeed_vic.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/intc/arm_gicv3.h"
+#include "trace.h"
+
+#define ASPEED_INTC_NR_IRQS 128
+#define ASPEED_INTC_SIZE 0x4000
+#define TO_REG(N) (N >> 2)
+
+uint64_t regs[ASPEED_INTC_SIZE];
+
+static void aspeed_intc_set_irq(void *opaque, int irq, int level)
+{
+}
+
+static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned size)
+{
+ AspeedINTCState *s = ASPEED_INTC(opaque);
+ GICv3State *gic = ARM_GICV3(s->gic);
+
+ uint64_t value = 0;
+ switch (TO_REG(offset)) {
+ case TO_REG(0x1404):
+ /* BMC UART interript is GICINT132[18] */
+ if (gic && gicv3_gicd_level_test(gic, 164)) {
+ value = BIT(18);
+ }
+ break;
+ default:
+ value = regs[TO_REG(offset)];
+ break;
+ }
+
+ return value;
+}
+
+static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
+ unsigned size)
+{
+ AspeedINTCState *s = ASPEED_INTC(opaque);
+ GICv3State *gic = ARM_GICV3(s->gic);
+
+ switch (TO_REG(offset)) {
+ case TO_REG(0x1400):
+ regs[TO_REG(offset)] = data;
+ if (regs[TO_REG(offset)]) {
+ gicv3_gicd_enabled_set(gic, 164);
+ } else {
+ gicv3_gicd_enabled_clear(gic, 164);
+ }
+ break;
+ case TO_REG(0x1404):
+ regs[TO_REG(offset)] &= ~(data);
+ gicv3_gicd_level_clear(gic, 164);
+ break;
+ default:
+ regs[TO_REG(offset)] = data;
+ break;
+ }
+}
+
+static const MemoryRegionOps aspeed_intc_ops = {
+ .read = aspeed_intc_read,
+ .write = aspeed_intc_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .valid.unaligned = false,
+};
+
+static void aspeed_intc_realize(DeviceState *dev, Error **errp)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ AspeedINTCState *s = ASPEED_INTC(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
+ TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->fiq);
+}
+
+static void aspeed_intc_reset(DeviceState *dev)
+{
+ AspeedINTCState *s = ASPEED_INTC(dev);
+
+ s->level = 0;
+ s->raw = 0;
+ s->select = 0;
+ s->enable = 0;
+ s->trigger = 0;
+ s->sense = 0x1F07FFF8FFFFULL;
+ s->dual_edge = 0xF800070000ULL;
+ s->event = 0x5F07FFF8FFFFULL;
+}
+
+static void aspeed_intc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = aspeed_intc_realize;
+ dc->reset = aspeed_intc_reset;
+ dc->desc = "ASPEED Interrupt Controller for AST27x0";
+ dc->vmsd = NULL;
+}
+
+static const TypeInfo aspeed_intc_info = {
+ .name = TYPE_ASPEED_INTC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AspeedINTCState),
+ .class_init = aspeed_intc_class_init,
+};
+
+static void aspeed_intc_register_types(void)
+{
+ type_register_static(&aspeed_intc_info);
+}
+
+type_init(aspeed_intc_register_types);
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index ed355941d1..f5c574f584 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -14,6 +14,7 @@ system_ss.add(when: 'CONFIG_ARM_GICV3_TCG', if_true: files(
))
system_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c'))
+system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_intc.c'))
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c'))
system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
diff --git a/include/hw/intc/aspeed_vic.h b/include/hw/intc/aspeed_vic.h
index 68d6ab997a..673a11d7fd 100644
--- a/include/hw/intc/aspeed_vic.h
+++ b/include/hw/intc/aspeed_vic.h
@@ -17,6 +17,7 @@
#include "qom/object.h"
#define TYPE_ASPEED_VIC "aspeed.vic"
+#define TYPE_ASPEED_INTC "aspeed.intc"
OBJECT_DECLARE_SIMPLE_TYPE(AspeedVICState, ASPEED_VIC)
#define ASPEED_VIC_NR_IRQS 51
@@ -46,4 +47,32 @@ struct AspeedVICState {
uint64_t event;
};
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedINTCState, ASPEED_INTC)
+
+struct AspeedINTCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ DeviceState *gic;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq irq;
+ qemu_irq fiq;
+
+ uint64_t level;
+ uint64_t raw;
+ uint64_t select;
+ uint64_t enable;
+ uint64_t trigger;
+
+ /* 0=edge, 1=level */
+ uint64_t sense;
+
+ /* 0=single-edge, 1=dual-edge */
+ uint64_t dual_edge;
+
+ /* 0=low-sensitive/falling-edge, 1=high-sensitive/rising-edge */
+ uint64_t event;
+};
+
#endif /* ASPEED_VIC_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v2 1/9] aspeed/wdt: Add AST2700 support
[not found] ` <20240304092934.1953198-2-jamin_lin@aspeedtech.com>
@ 2024-03-04 14:32 ` Cédric Le Goater
2024-03-05 3:08 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 14:32 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
Hello Jamin,
On 3/4/24 10:29, Jamin Lin wrote:
> AST2700 wdt controller is similiar to AST2600's wdt, but
> the AST2700 has 8 watchdogs, and they each have a 0x80 of registers.
... they each have 0x80 registers.
> Introduce ast2700 object class and increse the number of regs(offset) of
.. increase ...
> ast2700 model.
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Thanks,
C.
> ---
> hw/watchdog/wdt_aspeed.c | 24 ++++++++++++++++++++++++
> include/hw/watchdog/wdt_aspeed.h | 3 ++-
> 2 files changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> index d70b656f8e..75685c5647 100644
> --- a/hw/watchdog/wdt_aspeed.c
> +++ b/hw/watchdog/wdt_aspeed.c
> @@ -422,12 +422,36 @@ static const TypeInfo aspeed_1030_wdt_info = {
> .class_init = aspeed_1030_wdt_class_init,
> };
>
> +static void aspeed_2700_wdt_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
> +
> + dc->desc = "ASPEED 2700 Watchdog Controller";
> + awc->iosize = 0x80;
> + awc->ext_pulse_width_mask = 0xfffff; /* TODO */
> + awc->reset_ctrl_reg = AST2600_SCU_RESET_CONTROL1;
> + awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
> + awc->wdt_reload = aspeed_wdt_reload_1mhz;
> + awc->sanitize_ctrl = aspeed_2600_sanitize_ctrl;
> + awc->default_status = 0x014FB180;
> + awc->default_reload_value = 0x014FB180;
> +}
> +
> +static const TypeInfo aspeed_2700_wdt_info = {
> + .name = TYPE_ASPEED_2700_WDT,
> + .parent = TYPE_ASPEED_WDT,
> + .instance_size = sizeof(AspeedWDTState),
> + .class_init = aspeed_2700_wdt_class_init,
> +};
> +
> static void wdt_aspeed_register_types(void)
> {
> type_register_static(&aspeed_wdt_info);
> type_register_static(&aspeed_2400_wdt_info);
> type_register_static(&aspeed_2500_wdt_info);
> type_register_static(&aspeed_2600_wdt_info);
> + type_register_static(&aspeed_2700_wdt_info);
> type_register_static(&aspeed_1030_wdt_info);
> }
>
> diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
> index e90ef86651..830b0a7936 100644
> --- a/include/hw/watchdog/wdt_aspeed.h
> +++ b/include/hw/watchdog/wdt_aspeed.h
> @@ -19,9 +19,10 @@ OBJECT_DECLARE_TYPE(AspeedWDTState, AspeedWDTClass, ASPEED_WDT)
> #define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
> #define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
> #define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600"
> +#define TYPE_ASPEED_2700_WDT TYPE_ASPEED_WDT "-ast2700"
> #define TYPE_ASPEED_1030_WDT TYPE_ASPEED_WDT "-ast1030"
>
> -#define ASPEED_WDT_REGS_MAX (0x30 / 4)
> +#define ASPEED_WDT_REGS_MAX (0x80 / 4)
>
> struct AspeedWDTState {
> /*< private >*/
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 2/9] aspeed/sli: Add AST2700 support
[not found] ` <20240304092934.1953198-3-jamin_lin@aspeedtech.com>
@ 2024-03-04 14:36 ` Cédric Le Goater
2024-03-05 3:28 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 14:36 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
On 3/4/24 10:29, Jamin Lin wrote:
> AST2700 SLI engine is designed to accelerate the
> throughput between cross-die connections.
> It have CPU_SLI at CPU die and IO_SLI at IO die.
>
> Introduce new ast2700_sli and ast2700_sliio class
> with instance_init and realize handlers.
This should say that the implementation is a dummy one.
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> hw/misc/aspeed_sli.c | 179 +++++++++++++++++++++++++++++++++++
> hw/misc/meson.build | 3 +-
> hw/misc/trace-events | 7 ++
> include/hw/misc/aspeed_sli.h | 32 +++++++
> 4 files changed, 220 insertions(+), 1 deletion(-)
> create mode 100644 hw/misc/aspeed_sli.c
> create mode 100644 include/hw/misc/aspeed_sli.h
>
> diff --git a/hw/misc/aspeed_sli.c b/hw/misc/aspeed_sli.c
> new file mode 100644
> index 0000000000..4af42f145c
> --- /dev/null
> +++ b/hw/misc/aspeed_sli.c
> @@ -0,0 +1,179 @@
> +/*
> + * ASPEED SLI Controller
> + *
> + * Copyright (C) 2024 ASPEED Technology Inc.
> + *
> + * This code is licensed under the GPL version 2 or later. See
> + * the COPYING file in the top-level directory.
In all files, the paragraph above can be replaced with :
* SPDX-License-Identifier: GPL-2.0-or-later
Thanks,
C.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "qemu/error-report.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/misc/aspeed_sli.h"
> +#include "qapi/error.h"
> +#include "migration/vmstate.h"
> +#include "trace.h"
> +
> +#define SLI_REGION_SIZE 0x500
> +#define TO_REG(addr) ((addr) >> 2)
> +
> +static uint64_t aspeed_sli_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> + AspeedSLIState *s = ASPEED_SLI(opaque);
> + int reg = TO_REG(addr);
> +
> + if (reg >= ARRAY_SIZE(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, addr);
> + return 0;
> + }
> +
> + trace_aspeed_sli_read(addr, size, s->regs[reg]);
> + return s->regs[reg];
> +}
> +
> +static void aspeed_sli_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned int size)
> +{
> + AspeedSLIState *s = ASPEED_SLI(opaque);
> + int reg = TO_REG(addr);
> +
> + if (reg >= ARRAY_SIZE(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, addr);
> + return;
> + }
> +
> + trace_aspeed_sli_write(addr, size, data);
> + s->regs[reg] = data;
> +}
> +
> +static uint64_t aspeed_sliio_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> + AspeedSLIState *s = ASPEED_SLI(opaque);
> + int reg = TO_REG(addr);
> +
> + if (reg >= ARRAY_SIZE(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, addr);
> + return 0;
> + }
> +
> + trace_aspeed_sliio_read(addr, size, s->regs[reg]);
> + return s->regs[reg];
> +}
> +
> +static void aspeed_sliio_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned int size)
> +{
> + AspeedSLIState *s = ASPEED_SLI(opaque);
> + int reg = TO_REG(addr);
> +
> + if (reg >= ARRAY_SIZE(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, addr);
> + return;
> + }
> +
> + trace_aspeed_sliio_write(addr, size, data);
> + s->regs[reg] = data;
> +}
> +
> +static const MemoryRegionOps aspeed_sli_ops = {
> + .read = aspeed_sli_read,
> + .write = aspeed_sli_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid = {
> + .min_access_size = 1,
> + .max_access_size = 4,
> + },
> +};
> +
> +static const MemoryRegionOps aspeed_sliio_ops = {
> + .read = aspeed_sliio_read,
> + .write = aspeed_sliio_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid = {
> + .min_access_size = 1,
> + .max_access_size = 4,
> + },
> +};
> +
> +static void aspeed_sli_realize(DeviceState *dev, Error **errp)
> +{
> + AspeedSLIState *s = ASPEED_SLI(dev);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sli_ops, s,
> + TYPE_ASPEED_SLI, SLI_REGION_SIZE);
> + sysbus_init_mmio(sbd, &s->iomem);
> +}
> +
> +static void aspeed_sliio_realize(DeviceState *dev, Error **errp)
> +{
> + AspeedSLIState *s = ASPEED_SLI(dev);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sliio_ops, s,
> + TYPE_ASPEED_SLI, SLI_REGION_SIZE);
> + sysbus_init_mmio(sbd, &s->iomem);
> +}
> +
> +static void aspeed_sli_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->desc = "Aspeed SLI Controller";
> + dc->realize = aspeed_sli_realize;
> +}
> +
> +static const TypeInfo aspeed_sli_info = {
> + .name = TYPE_ASPEED_SLI,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(AspeedSLIState),
> + .class_init = aspeed_sli_class_init,
> + .class_size = sizeof(AspeedSLIClass),
> + .abstract = true,
> +};
> +
> +static void aspeed_2700_sli_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->desc = "AST2700 SLI Controller";
> +}
> +
> +static void aspeed_2700_sliio_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->desc = "AST2700 I/O SLI Controller";
> + dc->realize = aspeed_sliio_realize;
> +}
> +
> +static const TypeInfo aspeed_2700_sli_info = {
> + .name = TYPE_ASPEED_2700_SLI,
> + .parent = TYPE_ASPEED_SLI,
> + .class_init = aspeed_2700_sli_class_init,
> +};
> +
> +static const TypeInfo aspeed_2700_sliio_info = {
> + .name = TYPE_ASPEED_2700_SLIIO,
> + .parent = TYPE_ASPEED_SLI,
> + .class_init = aspeed_2700_sliio_class_init,
> +};
> +
> +static void aspeed_sli_register_types(void)
> +{
> + type_register_static(&aspeed_sli_info);
> + type_register_static(&aspeed_2700_sli_info);
> + type_register_static(&aspeed_2700_sliio_info);
> +}
> +
> +type_init(aspeed_sli_register_types);
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 746686835b..790f05525a 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -137,7 +137,8 @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
> 'aspeed_sbc.c',
> 'aspeed_sdmc.c',
> 'aspeed_xdma.c',
> - 'aspeed_peci.c'))
> + 'aspeed_peci.c',
> + 'aspeed_sli.c'))
>
> system_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
> system_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c'))
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events
> index 5f5bc92222..07010a7ea6 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -341,3 +341,10 @@ djmemc_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRI
> # iosb.c
> iosb_read(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
> iosb_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
> +
> +# aspeed_sli.c
> +aspeed_sli_write(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_sli_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_sliio_write(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_sliio_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +
> diff --git a/include/hw/misc/aspeed_sli.h b/include/hw/misc/aspeed_sli.h
> new file mode 100644
> index 0000000000..15892950e2
> --- /dev/null
> +++ b/include/hw/misc/aspeed_sli.h
> @@ -0,0 +1,32 @@
> +/*
> + * ASPEED SLI Controller
> + *
> + * Copyright (C) 2024 ASPEED Technology Inc.
> + *
> + * This code is licensed under the GPL version 2 or later. See
> + * the COPYING file in the top-level directory.
> + */
> +#ifndef ASPEED_SLI_H
> +#define ASPEED_SLI_H
> +
> +#include "hw/sysbus.h"
> +
> +#define TYPE_ASPEED_SLI "aspeed.sli"
> +#define TYPE_ASPEED_2700_SLI TYPE_ASPEED_SLI "-ast2700"
> +#define TYPE_ASPEED_2700_SLIIO TYPE_ASPEED_SLI "io" "-ast2700"
> +OBJECT_DECLARE_TYPE(AspeedSLIState, AspeedSLIClass, ASPEED_SLI)
> +
> +#define ASPEED_SLI_NR_REGS (0x500 >> 2)
> +
> +struct AspeedSLIState {
> + SysBusDevice parent;
> + MemoryRegion iomem;
> +
> + uint32_t regs[ASPEED_SLI_NR_REGS];
> +};
> +
> +struct AspeedSLIClass {
> + SysBusDeviceClass parent_class;
> +};
> +
> +#endif /* ASPEED_SLI_H */
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
2024-03-04 9:29 ` [PATCH v2 3/9] aspeed/sdmc: " Jamin Lin via
@ 2024-03-04 14:47 ` Cédric Le Goater
2024-03-11 7:21 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 14:47 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
On 3/4/24 10:29, Jamin Lin wrote:
> The SDRAM memory controller(DRAMC) controls the access to external
> DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
>
> The DRAM memory controller of AST2700 is not backward compatible
> to previous chips such AST2600, AST2500 and AST2400.
>
> Max memory is now 8GiB on the AST2700. Introduce new
> aspeed_2700_sdmc and class with read/write operation and
> reset handlers.
>
> Define DRAMC necessary protected registers and
> unprotected registers for AST2700 and increase
> the register set to 0x1000.
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> hw/misc/aspeed_sdmc.c | 215 ++++++++++++++++++++++++++++++----
> include/hw/misc/aspeed_sdmc.h | 4 +-
> 2 files changed, 198 insertions(+), 21 deletions(-)
>
> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
> index 64cd1a81dc..63fb7936c4 100644
> --- a/hw/misc/aspeed_sdmc.c
> +++ b/hw/misc/aspeed_sdmc.c
> @@ -27,6 +27,7 @@
> #define PROT_SOFTLOCKED 0x00
>
> #define PROT_KEY_UNLOCK 0xFC600309
> +#define PROT_2700_KEY_UNLOCK 0x1688A8A8
> #define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
>
> /* Configuration Register */
> @@ -54,6 +55,46 @@
> #define R_DRAM_TIME (0x8c / 4)
> #define R_ECC_ERR_INJECT (0xb4 / 4)
>
> +/* AST2700 Register */
> +#define R_2700_PROT (0x00 / 4)
> +#define R_INT_STATUS (0x04 / 4)
> +#define R_INT_CLEAR (0x08 / 4)
> +#define R_INT_MASK (0x0c / 4)
> +#define R_MAIN_CONF (0x10 / 4)
> +#define R_MAIN_CONTROL (0x14 / 4)
> +#define R_MAIN_STATUS (0x18 / 4)
> +#define R_ERR_STATUS (0x1c / 4)
> +#define R_ECC_FAIL_STATUS (0x78 / 4)
> +#define R_ECC_FAIL_ADDR (0x7c / 4)
> +#define R_ECC_TESTING_CONTROL (0x80 / 4)
> +#define R_PROT_REGION_LOCK_STATUS (0x94 / 4)
> +#define R_TEST_FAIL_ADDR (0xd4 / 4)
> +#define R_TEST_FAIL_D0 (0xd8 / 4)
> +#define R_TEST_FAIL_D1 (0xdc / 4)
> +#define R_TEST_FAIL_D2 (0xe0 / 4)
> +#define R_TEST_FAIL_D3 (0xe4 / 4)
> +#define R_DBG_STATUS (0xf4 / 4)
> +#define R_PHY_INTERFACE_STATUS (0xf8 / 4)
> +#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4)
> +#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4)
> +#define R_PORT0_INTERFACE_MONITOR1 (0x244 / 4)
> +#define R_PORT0_INTERFACE_MONITOR2 (0x248 / 4)
> +#define R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4)
> +#define R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4)
> +#define R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4)
> +#define R_PORT2_INTERFACE_MONITOR0 (0x340 / 4)
> +#define R_PORT2_INTERFACE_MONITOR1 (0x344 / 4)
> +#define R_PORT2_INTERFACE_MONITOR2 (0x348 / 4)
> +#define R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4)
> +#define R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4)
> +#define R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4)
> +#define R_PORT4_INTERFACE_MONITOR0 (0x440 / 4)
> +#define R_PORT4_INTERFACE_MONITOR1 (0x444 / 4)
> +#define R_PORT4_INTERFACE_MONITOR2 (0x448 / 4)
> +#define R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4)
> +#define R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4)
> +#define R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4)
> +
> /*
> * Configuration register Ox4 (for Aspeed AST2400 SOC)
> *
> @@ -76,10 +117,6 @@
> #define ASPEED_SDMC_VGA_32MB 0x2
> #define ASPEED_SDMC_VGA_64MB 0x3
> #define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
> -#define ASPEED_SDMC_DRAM_64MB 0x0
> -#define ASPEED_SDMC_DRAM_128MB 0x1
> -#define ASPEED_SDMC_DRAM_256MB 0x2
> -#define ASPEED_SDMC_DRAM_512MB 0x3
>
> #define ASPEED_SDMC_READONLY_MASK \
> (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
> @@ -100,22 +137,24 @@
> #define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs from AST2400 */
> #define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs from AST2400 */
>
> -/* DRAM size definitions differs */
> -#define ASPEED_SDMC_AST2500_128MB 0x0
> -#define ASPEED_SDMC_AST2500_256MB 0x1
> -#define ASPEED_SDMC_AST2500_512MB 0x2
> -#define ASPEED_SDMC_AST2500_1024MB 0x3
> -
> -#define ASPEED_SDMC_AST2600_256MB 0x0
> -#define ASPEED_SDMC_AST2600_512MB 0x1
> -#define ASPEED_SDMC_AST2600_1024MB 0x2
> -#define ASPEED_SDMC_AST2600_2048MB 0x3
> -
Please move the removal above in a separate patch.
> #define ASPEED_SDMC_AST2500_READONLY_MASK \
> (ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \
> ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
> ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
>
> +/*
> + * Main Configuration register Ox10 (for Aspeed AST2700 SOC and higher)
> + *
> + */
> +#define ASPEED_SDMC_AST2700_RESERVED 0xFFFF2082 /* 31:16, 13, 7, 1 */
> +#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8)
> +#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6)
> +#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE (1 << 5)
> +#define ASPEED_SDMC_AST2700_DRAM_SIZE(x) ((x & 0x7) << 2)
> +
> +#define ASPEED_SDMC_AST2700_READONLY_MASK \
> + (ASPEED_SDMC_AST2700_RESERVED)
> +
> static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
> {
> AspeedSDMCState *s = ASPEED_SDMC(opaque);
> @@ -231,7 +270,10 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
> AspeedSDMCState *s = ASPEED_SDMC(dev);
> AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
>
> - assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> + if (!asc->is_bus64bit) {
> + assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> + }
May be :
assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
?
> +
> s->max_ram_size = asc->max_ram_size;
>
> memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
> @@ -311,7 +353,8 @@ static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> uint32_t data)
> {
> if (reg == R_PROT) {
> - s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
> + s->regs[reg] =
> + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
> return;
> }
>
> @@ -369,7 +412,8 @@ static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> uint32_t data)
> {
> if (reg == R_PROT) {
> - s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
> + s->regs[reg] =
> + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
> return;
> }
>
> @@ -449,8 +493,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> }
>
> if (s->regs[R_PROT] == PROT_HARDLOCKED) {
> - qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n",
> - __func__);
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: SDMC is locked until system reset!\n",
> + __func__);
> return;
> }
The checkpatch changes could be in a separate patch. This is minor.
>
> @@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info = {
> .class_init = aspeed_2600_sdmc_class_init,
> };
>
> +static void aspeed_2700_sdmc_reset(DeviceState *dev)
> +{
> + AspeedSDMCState *s = ASPEED_SDMC(dev);
> + AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> +
> + memset(s->regs, 0, sizeof(s->regs));
> +
> + /* Set ram size bit and defaults values */
> + s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
> + s->regs[R_2700_PROT] = PROT_UNLOCKED;
The default reset value is unlocked ?
Thanks,
C.
> +}
> +
> +static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
> +{
> + uint32_t fixed_conf = ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
> + ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
> +
> + /* Make sure readonly bits are kept */
> + data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
> +
> + return data | fixed_conf;
> +}
> +
> +static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> + uint32_t data)
> +{
> + /* Unprotected registers */
> + switch (reg) {
> + case R_INT_STATUS:
> + case R_INT_CLEAR:
> + case R_INT_MASK:
> + case R_MAIN_STATUS:
> + case R_ERR_STATUS:
> + case R_ECC_FAIL_STATUS:
> + case R_ECC_FAIL_ADDR:
> + case R_PROT_REGION_LOCK_STATUS:
> + case R_TEST_FAIL_ADDR:
> + case R_TEST_FAIL_D0:
> + case R_TEST_FAIL_D1:
> + case R_TEST_FAIL_D2:
> + case R_TEST_FAIL_D3:
> + case R_DBG_STATUS:
> + case R_PHY_INTERFACE_STATUS:
> + case R_GRAPHIC_MEM_BASE_ADDR:
> + case R_PORT0_INTERFACE_MONITOR0:
> + case R_PORT0_INTERFACE_MONITOR1:
> + case R_PORT0_INTERFACE_MONITOR2:
> + case R_PORT1_INTERFACE_MONITOR0:
> + case R_PORT1_INTERFACE_MONITOR1:
> + case R_PORT1_INTERFACE_MONITOR2:
> + case R_PORT2_INTERFACE_MONITOR0:
> + case R_PORT2_INTERFACE_MONITOR1:
> + case R_PORT2_INTERFACE_MONITOR2:
> + case R_PORT3_INTERFACE_MONITOR0:
> + case R_PORT3_INTERFACE_MONITOR1:
> + case R_PORT3_INTERFACE_MONITOR2:
> + case R_PORT4_INTERFACE_MONITOR0:
> + case R_PORT4_INTERFACE_MONITOR1:
> + case R_PORT4_INTERFACE_MONITOR2:
> + case R_PORT5_INTERFACE_MONITOR0:
> + case R_PORT5_INTERFACE_MONITOR1:
> + case R_PORT5_INTERFACE_MONITOR2:
> + s->regs[reg] = data;
> + return;
> + }
> +
> + if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: SDMC is locked until system reset!\n",
> + __func__);
> + return;
> + }
> +
> + if (reg != R_2700_PROT && s->regs[R_2700_PROT] == PROT_SOFTLOCKED) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: SDMC is locked! (write to MCR%02x blocked)\n",
> + __func__, reg * 4);
> + return;
> + }
> +
> + switch (reg) {
> + case R_2700_PROT:
> + if (data == PROT_2700_KEY_UNLOCK) {
> + data = PROT_UNLOCKED;
> + } else if (data == PROT_KEY_HARDLOCK) {
> + data = PROT_HARDLOCKED;
> + } else {
> + data = PROT_SOFTLOCKED;
> + }
> + break;
> + case R_MAIN_CONF:
> + data = aspeed_2700_sdmc_compute_conf(s, data);
> + break;
> + case R_MAIN_STATUS:
> + /* Will never return 'busy'. */
> + data &= ~PHY_BUSY_STATE;
> + break;
> + default:
> + break;
> + }
> +
> + s->regs[reg] = data;
> +}
> +
> +static const uint64_t
> + aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
> + 2048 * MiB, 4096 * MiB, 8192 * MiB, 0};
> +
> +static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
> +
> + dc->desc = "ASPEED 2700 SDRAM Memory Controller";
> + dc->reset = aspeed_2700_sdmc_reset;
> +
> + asc->is_bus64bit = true;
> + asc->max_ram_size = 8 * GiB;
> + asc->compute_conf = aspeed_2700_sdmc_compute_conf;
> + asc->write = aspeed_2700_sdmc_write;
> + asc->valid_ram_sizes = aspeed_2700_ram_sizes;
> +}
> +
> +static const TypeInfo aspeed_2700_sdmc_info = {
> + .name = TYPE_ASPEED_2700_SDMC,
> + .parent = TYPE_ASPEED_SDMC,
> + .class_init = aspeed_2700_sdmc_class_init,
> +};
> +
> static void aspeed_sdmc_register_types(void)
> {
> type_register_static(&aspeed_sdmc_info);
> type_register_static(&aspeed_2400_sdmc_info);
> type_register_static(&aspeed_2500_sdmc_info);
> type_register_static(&aspeed_2600_sdmc_info);
> + type_register_static(&aspeed_2700_sdmc_info);
> }
>
> type_init(aspeed_sdmc_register_types);
> diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
> index ec2d59a14f..6df2f0a3b7 100644
> --- a/include/hw/misc/aspeed_sdmc.h
> +++ b/include/hw/misc/aspeed_sdmc.h
> @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
> #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
> #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
> #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
> +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
>
> /*
> * SDMC has 174 documented registers. In addition the u-boot device tree
> @@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
> * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
> * training.
> */
> -#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
> +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
>
> struct AspeedSDMCState {
> /*< private >*/
> @@ -51,6 +52,7 @@ struct AspeedSDMCClass {
> const uint64_t *valid_ram_sizes;
> uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
> void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
> + bool is_bus64bit;
> };
>
> #endif /* ASPEED_SDMC_H */
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 4/9] aspeed/smc: Add AST2700 support
2024-03-04 9:29 ` [PATCH v2 4/9] aspeed/smc: " Jamin Lin via
@ 2024-03-04 15:19 ` Cédric Le Goater
2024-03-12 9:58 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 15:19 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
On 3/4/24 10:29, Jamin Lin wrote:
> AST2700 fmc/spi controller's address decoding unit is 64KB
> and only bits [31:16] are used for decoding. Introduce seg_to_reg
> and reg_to_seg handlers for ast2700 fmc/spi controller.
> In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler.
>
> AST2700 support the maximum dram size is 8GiB.
> Update dma_rw function and trace-event to support 64 bits dram
> address. DMA length is from 1 byte to 32MB for AST2700, AST2600 and AST10x0
> and DMA length is from 4 bytes to 32MB for AST2500.
>
> In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
> data for AST2700, AST2600 and AST10x0 and 4 bytes data for AST2500.
> To support all ASPEED SOCs, adds dma_start_length parameter to store
> the start length and update DMA_LENGTH mask to "1FFFFFF" to fix dma moving
> incorrect data length issue.
>
> Currently, dma_rw function only supports length 4 bytes aligned.
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> hw/ssi/aspeed_smc.c | 326 +++++++++++++++++++++++++++++++++---
> hw/ssi/trace-events | 2 +-
> include/hw/ssi/aspeed_smc.h | 1 +
> 3 files changed, 309 insertions(+), 20 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 3c93936fd1..73121edf2b 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -131,6 +131,9 @@
> #define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */
> #define FMC_WDT2_CTRL_EN BIT(0)
>
> +/* DMA DRAM Side Address High Part (AST2700) */
> +#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4)
> +
> /* DMA Control/Status Register */
> #define R_DMA_CTRL (0x80 / 4)
> #define DMA_CTRL_REQUEST (1 << 31)
> @@ -177,13 +180,18 @@
> * DMA flash addresses should be 4 bytes aligned and the valid address
> * range is 0x20000000 - 0x2FFFFFFF.
> *
> - * DMA length is from 4 bytes to 32MB
> + * DMA length is from 4 bytes to 32MB (AST2500)
> * 0: 4 bytes
> * 0x7FFFFF: 32M bytes
> + *
> + * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700)
> + * 0: 1 byte
> + * 0x1FFFFFF: 32M bytes
OK. Then, we need to fix the model first before adding AST2700 support.
> */
> #define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask)
> +#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf)
> #define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask)
> -#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
> +#define DMA_LENGTH(val) ((val) & 0x01FFFFFF)
>
> /* Flash opcodes. */
> #define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
> @@ -202,6 +210,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
> #define ASPEED_SMC_FEATURE_DMA 0x1
> #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
> #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
> +#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
>
> static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
> {
> @@ -213,6 +222,11 @@ static inline bool aspeed_smc_has_wdt_control(const AspeedSMCClass *asc)
> return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
> }
>
> +static inline bool aspeed_smc_has_dma_dram_addr_high(const AspeedSMCClass *asc)
> +{
> + return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
> +}
> +
> #define aspeed_smc_error(fmt, ...) \
> qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
>
> @@ -655,7 +669,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
> .endianness = DEVICE_LITTLE_ENDIAN,
> .valid = {
> .min_access_size = 1,
> - .max_access_size = 4,
> + .max_access_size = 8,
> },
> };
>
> @@ -734,6 +748,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
> (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
> (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) ||
> (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) ||
> + (aspeed_smc_has_dma(asc) &&
> + aspeed_smc_has_dma_dram_addr_high(asc) &&
> + addr == R_DMA_DRAM_ADDR_HIGH) ||
> (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
> (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
> (addr >= R_SEG_ADDR0 &&
> @@ -840,8 +857,11 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
> */
> static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> {
> + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> MemTxResult result;
> + uint32_t dma_len;
> uint32_t data;
> + uint32_t extra;
>
> if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
> aspeed_smc_error("invalid direction for DMA checksum");
> @@ -852,7 +872,14 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> aspeed_smc_dma_calibration(s);
> }
>
> - while (s->regs[R_DMA_LEN]) {
> + dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
> + /* dma length 4 bytes aligned */
> + extra = dma_len % 4;
> + if (extra != 0) {
> + dma_len += 4 - extra;
> + }
> +
> + while (dma_len) {
> data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
> MEMTXATTRS_UNSPECIFIED, &result);
> if (result != MEMTX_OK) {
> @@ -868,7 +895,8 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> */
> s->regs[R_DMA_CHECKSUM] += data;
> s->regs[R_DMA_FLASH_ADDR] += 4;
> - s->regs[R_DMA_LEN] -= 4;
> + dma_len -= 4;
> + s->regs[R_DMA_LEN] = dma_len;
> }
>
> if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
> @@ -879,21 +907,44 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
>
> static void aspeed_smc_dma_rw(AspeedSMCState *s)
> {
> + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> + uint64_t dram_addr_high;
> + uint64_t dma_dram_addr;
> + uint64_t dram_addr;
> MemTxResult result;
> + uint32_t dma_len;
> uint32_t data;
> + uint32_t extra;
> +
> + if (aspeed_smc_has_dma_dram_addr_high(asc)) {
> + dram_addr_high = s->regs[R_DMA_DRAM_ADDR_HIGH];
> + dram_addr_high <<= 32;
> + dma_dram_addr = dram_addr_high | s->regs[R_DMA_DRAM_ADDR];
> + dram_addr = dma_dram_addr - s->dram_mr->container->addr;
> + } else {
> + dma_dram_addr = s->regs[R_DMA_DRAM_ADDR];
> + dram_addr = dma_dram_addr;
> + }
> +
> + dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
> + /* dma length 4 bytes aligned */
> + extra = dma_len % 4;
> + if (extra != 0) {
> + dma_len += 4 - extra;
> + }
I find the calculation in aspeed_smc_dma_checksum() and aspeed_smc_dma_rw()
confusing. Can you please add helper routines to compute DMA_DRAM_ADDR and
DMA_LEN ? Please do that in a separate patch before adding AST2700 support.
Thanks,
C.
> trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
> "write" : "read",
> s->regs[R_DMA_FLASH_ADDR],
> - s->regs[R_DMA_DRAM_ADDR],
> - s->regs[R_DMA_LEN]);
> - while (s->regs[R_DMA_LEN]) {
> + dram_addr,
> + dma_len);
> +
> + while (dma_len) {
> if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
> - data = address_space_ldl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
> + data = address_space_ldl_le(&s->dram_as, dram_addr,
> MEMTXATTRS_UNSPECIFIED, &result);
> if (result != MEMTX_OK) {
> - aspeed_smc_error("DRAM read failed @%08x",
> - s->regs[R_DMA_DRAM_ADDR]);
> + aspeed_smc_error("DRAM read failed @%" PRIx64, dram_addr);
> return;
> }
>
> @@ -913,11 +964,10 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
> return;
> }
>
> - address_space_stl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
> + address_space_stl_le(&s->dram_as, dram_addr,
> data, MEMTXATTRS_UNSPECIFIED, &result);
> if (result != MEMTX_OK) {
> - aspeed_smc_error("DRAM write failed @%08x",
> - s->regs[R_DMA_DRAM_ADDR]);
> + aspeed_smc_error("DRAM write failed @%" PRIx64, dram_addr);
> return;
> }
> }
> @@ -926,10 +976,18 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
> * When the DMA is on-going, the DMA registers are updated
> * with the current working addresses and length.
> */
> + dram_addr += 4;
> + dma_dram_addr += 4;
> + if (aspeed_smc_has_dma_dram_addr_high(asc)) {
> + dram_addr_high = dma_dram_addr >> 32;
> + s->regs[R_DMA_DRAM_ADDR_HIGH] = dram_addr_high;
> + }
> +
> + s->regs[R_DMA_DRAM_ADDR] = dma_dram_addr & 0xffffffff;
> s->regs[R_DMA_FLASH_ADDR] += 4;
> - s->regs[R_DMA_DRAM_ADDR] += 4;
> - s->regs[R_DMA_LEN] -= 4;
> s->regs[R_DMA_CHECKSUM] += data;
> + dma_len -= 4;
> + s->regs[R_DMA_LEN] = dma_len;
> }
> }
>
> @@ -1079,6 +1137,10 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
> } else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN &&
> aspeed_smc_dma_granted(s)) {
> s->regs[addr] = DMA_LENGTH(value);
> + } else if (aspeed_smc_has_dma(asc) &&
> + aspeed_smc_has_dma_dram_addr_high(asc) &&
> + addr == R_DMA_DRAM_ADDR_HIGH) {
> + s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
> } else {
> qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
> __func__, addr);
> @@ -1372,6 +1434,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x1FFFFFFC;
> + asc->dma_start_length = 4;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_smc_reg_to_segment;
> @@ -1439,7 +1502,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
> DeviceClass *dc = DEVICE_CLASS(klass);
> AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
>
> - dc->desc = "Aspeed 2600 FMC Controller";
> + dc->desc = "Aspeed 2500 FMC Controller";
> asc->r_conf = R_CONF;
> asc->r_ce_ctrl = R_CE_CTRL;
> asc->r_ctrl0 = R_CTRL0;
> @@ -1455,6 +1518,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 4;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_smc_reg_to_segment;
> @@ -1477,7 +1541,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass *klass, void *data)
> DeviceClass *dc = DEVICE_CLASS(klass);
> AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
>
> - dc->desc = "Aspeed 2600 SPI1 Controller";
> + dc->desc = "Aspeed 2500 SPI1 Controller";
> asc->r_conf = R_CONF;
> asc->r_ce_ctrl = R_CE_CTRL;
> asc->r_ctrl0 = R_CTRL0;
> @@ -1512,7 +1576,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass *klass, void *data)
> DeviceClass *dc = DEVICE_CLASS(klass);
> AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
>
> - dc->desc = "Aspeed 2600 SPI2 Controller";
> + dc->desc = "Aspeed 2500 SPI2 Controller";
> asc->r_conf = R_CONF;
> asc->r_ce_ctrl = R_CE_CTRL;
> asc->r_ctrl0 = R_CTRL0;
> @@ -1611,6 +1675,7 @@ static void aspeed_2600_fmc_class_init(ObjectClass *klass, void *data)
> ASPEED_SMC_FEATURE_WDT_CONTROL;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1649,6 +1714,7 @@ static void aspeed_2600_spi1_class_init(ObjectClass *klass, void *data)
> ASPEED_SMC_FEATURE_DMA_GRANT;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1688,6 +1754,7 @@ static void aspeed_2600_spi2_class_init(ObjectClass *klass, void *data)
> ASPEED_SMC_FEATURE_DMA_GRANT;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1769,6 +1836,7 @@ static void aspeed_1030_fmc_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x000BFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_1030_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_1030_smc_reg_to_segment;
> @@ -1806,6 +1874,7 @@ static void aspeed_1030_spi1_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x000BFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1842,6 +1911,7 @@ static void aspeed_1030_spi2_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x000BFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1854,6 +1924,220 @@ static const TypeInfo aspeed_1030_spi2_info = {
> .class_init = aspeed_1030_spi2_class_init,
> };
>
> +/*
> + * The FMC Segment Registers of the AST2700 have a 64KB unit.
> + * Only bits [31:16] are used for decoding.
> + */
> +#define AST2700_SEG_ADDR_MASK 0xffff0000
> +
> +static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState *s,
> + const AspeedSegments *seg)
> +{
> + uint32_t reg = 0;
> +
> + /* Disabled segments have a nil register */
> + if (!seg->size) {
> + return 0;
> + }
> +
> + reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset */
> + reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /* end offset */
> + return reg;
> +}
> +
> +static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s,
> + uint32_t reg, AspeedSegments *seg)
> +{
> + uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK;
> + uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK;
> + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> +
> + if (reg) {
> + seg->addr = asc->flash_window_base + start_offset;
> + seg->size = end_offset + (64 * KiB) - start_offset;
> + } else {
> + seg->addr = asc->flash_window_base;
> + seg->size = 0;
> + }
> +}
> +
> +static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = {
> + [R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 |
> + CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1),
> + [R_CE_CTRL] = 0x0000aa00,
> + [R_CTRL0] = 0x406b0641,
> + [R_CTRL1] = 0x00000400,
> + [R_CTRL2] = 0x00000400,
> + [R_CTRL3] = 0x00000400,
> + [R_SEG_ADDR0] = 0x08000000,
> + [R_SEG_ADDR1] = 0x10000800,
> + [R_SEG_ADDR2] = 0x00000000,
> + [R_SEG_ADDR3] = 0x00000000,
> + [R_DUMMY_DATA] = 0x00010000,
> + [R_DMA_DRAM_ADDR_HIGH] = 0x00000000,
> + [R_TIMINGS] = 0x007b0000,
> +};
> +
> +static const AspeedSegments aspeed_2700_fmc_segments[] = {
> + { 0x0, 128 * MiB }, /* start address is readonly */
> + { 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
> + { 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
> + { 0x0, 0 }, /* disabled */
> +};
> +
> +static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> +
> + dc->desc = "Aspeed 2700 FMC Controller";
> + asc->r_conf = R_CONF;
> + asc->r_ce_ctrl = R_CE_CTRL;
> + asc->r_ctrl0 = R_CTRL0;
> + asc->r_timings = R_TIMINGS;
> + asc->nregs_timings = 3;
> + asc->conf_enable_w0 = CONF_ENABLE_W0;
> + asc->cs_num_max = 3;
> + asc->segments = aspeed_2700_fmc_segments;
> + asc->segment_addr_mask = 0xffffffff;
> + asc->resets = aspeed_2700_fmc_resets;
> + asc->flash_window_base = 0x100000000;
> + asc->flash_window_size = 1 * GiB;
> + asc->features = ASPEED_SMC_FEATURE_DMA |
> + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> + asc->dma_flash_mask = 0x2FFFFFFC;
> + asc->dma_dram_mask = 0xFFFFFFFC;
> + asc->dma_start_length = 1;
> + asc->nregs = ASPEED_SMC_R_MAX;
> + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> +}
> +
> +static const TypeInfo aspeed_2700_fmc_info = {
> + .name = "aspeed.fmc-ast2700",
> + .parent = TYPE_ASPEED_SMC,
> + .class_init = aspeed_2700_fmc_class_init,
> +};
> +
> +static const AspeedSegments aspeed_2700_spi0_segments[] = {
> + { 0x0, 128 * MiB }, /* start address is readonly */
> + { 128 * MiB, 128 * MiB }, /* start address is readonly */
> + { 0x0, 0 }, /* disabled */
> +};
> +
> +static void aspeed_2700_spi0_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> +
> + dc->desc = "Aspeed 2700 SPI0 Controller";
> + asc->r_conf = R_CONF;
> + asc->r_ce_ctrl = R_CE_CTRL;
> + asc->r_ctrl0 = R_CTRL0;
> + asc->r_timings = R_TIMINGS;
> + asc->nregs_timings = 2;
> + asc->conf_enable_w0 = CONF_ENABLE_W0;
> + asc->cs_num_max = 2;
> + asc->segments = aspeed_2700_spi0_segments;
> + asc->segment_addr_mask = 0xffffffff;
> + asc->flash_window_base = 0x180000000;
> + asc->flash_window_size = 1 * GiB;
> + asc->features = ASPEED_SMC_FEATURE_DMA |
> + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> + asc->dma_flash_mask = 0x2FFFFFFC;
> + asc->dma_dram_mask = 0xFFFFFFFC;
> + asc->dma_start_length = 1;
> + asc->nregs = ASPEED_SMC_R_MAX;
> + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> +}
> +
> +static const TypeInfo aspeed_2700_spi0_info = {
> + .name = "aspeed.spi0-ast2700",
> + .parent = TYPE_ASPEED_SMC,
> + .class_init = aspeed_2700_spi0_class_init,
> +};
> +
> +static const AspeedSegments aspeed_2700_spi1_segments[] = {
> + { 0x0, 128 * MiB }, /* start address is readonly */
> + { 0x0, 0 }, /* disabled */
> +};
> +
> +static void aspeed_2700_spi1_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> +
> + dc->desc = "Aspeed 2700 SPI1 Controller";
> + asc->r_conf = R_CONF;
> + asc->r_ce_ctrl = R_CE_CTRL;
> + asc->r_ctrl0 = R_CTRL0;
> + asc->r_timings = R_TIMINGS;
> + asc->nregs_timings = 2;
> + asc->conf_enable_w0 = CONF_ENABLE_W0;
> + asc->cs_num_max = 2;
> + asc->segments = aspeed_2700_spi1_segments;
> + asc->segment_addr_mask = 0xffffffff;
> + asc->flash_window_base = 0x200000000;
> + asc->flash_window_size = 1 * GiB;
> + asc->features = ASPEED_SMC_FEATURE_DMA |
> + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> + asc->dma_flash_mask = 0x2FFFFFFC;
> + asc->dma_dram_mask = 0xFFFFFFFC;
> + asc->dma_start_length = 1;
> + asc->nregs = ASPEED_SMC_R_MAX;
> + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> +}
> +
> +static const TypeInfo aspeed_2700_spi1_info = {
> + .name = "aspeed.spi1-ast2700",
> + .parent = TYPE_ASPEED_SMC,
> + .class_init = aspeed_2700_spi1_class_init,
> +};
> +
> +static const AspeedSegments aspeed_2700_spi2_segments[] = {
> + { 0x0, 128 * MiB }, /* start address is readonly */
> + { 0x0, 0 }, /* disabled */
> +};
> +
> +static void aspeed_2700_spi2_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> +
> + dc->desc = "Aspeed 2700 SPI2 Controller";
> + asc->r_conf = R_CONF;
> + asc->r_ce_ctrl = R_CE_CTRL;
> + asc->r_ctrl0 = R_CTRL0;
> + asc->r_timings = R_TIMINGS;
> + asc->nregs_timings = 2;
> + asc->conf_enable_w0 = CONF_ENABLE_W0;
> + asc->cs_num_max = 2;
> + asc->segments = aspeed_2700_spi2_segments;
> + asc->segment_addr_mask = 0xffffffff;
> + asc->flash_window_base = 0x280000000;
> + asc->flash_window_size = 1 * GiB;
> + asc->features = ASPEED_SMC_FEATURE_DMA |
> + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> + asc->dma_flash_mask = 0x0FFFFFFC;
> + asc->dma_dram_mask = 0xFFFFFFFC;
> + asc->dma_start_length = 1;
> + asc->nregs = ASPEED_SMC_R_MAX;
> + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> +}
> +
> +static const TypeInfo aspeed_2700_spi2_info = {
> + .name = "aspeed.spi2-ast2700",
> + .parent = TYPE_ASPEED_SMC,
> + .class_init = aspeed_2700_spi2_class_init,
> +};
> +
> static void aspeed_smc_register_types(void)
> {
> type_register_static(&aspeed_smc_flash_info);
> @@ -1870,6 +2154,10 @@ static void aspeed_smc_register_types(void)
> type_register_static(&aspeed_1030_fmc_info);
> type_register_static(&aspeed_1030_spi1_info);
> type_register_static(&aspeed_1030_spi2_info);
> + type_register_static(&aspeed_2700_fmc_info);
> + type_register_static(&aspeed_2700_spi0_info);
> + type_register_static(&aspeed_2700_spi1_info);
> + type_register_static(&aspeed_2700_spi2_info);
> }
>
> type_init(aspeed_smc_register_types)
> diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
> index 2d5bd2b83d..7b5ad6a939 100644
> --- a/hw/ssi/trace-events
> +++ b/hw/ssi/trace-events
> @@ -6,7 +6,7 @@ aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x d
> aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
> aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
> aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
> -aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
> +aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint64_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%" PRIx64 " size:0x%08x"
> aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
> aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
>
> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> index 8e1dda556b..f359ed22cc 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -106,6 +106,7 @@ struct AspeedSMCClass {
> uint32_t features;
> hwaddr dma_flash_mask;
> hwaddr dma_dram_mask;
> + uint32_t dma_start_length;
> uint32_t nregs;
> uint32_t (*segment_to_reg)(const AspeedSMCState *s,
> const AspeedSegments *seg);
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 5/9] aspeed/scu: Add AST2700 support
2024-03-04 9:29 ` [PATCH v2 5/9] aspeed/scu: " Jamin Lin via
@ 2024-03-04 15:37 ` Cédric Le Goater
0 siblings, 0 replies; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 15:37 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
On 3/4/24 10:29, Jamin Lin wrote:
> AST2700 have two SCU controllers which are SCU and SCUIO.
> Both SCU and SCUIO registers are not compatible previous SOCs
> , introduces new registers and adds ast2700 scu, sucio class init handler.
>
> The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
> the pclk divider selection of SCU is defined in SCU280[25:23].
> Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
> and trace-event for AST2700 SCU and SCUIO.
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Thanks,
C.
> ---
> hw/misc/aspeed_scu.c | 306 ++++++++++++++++++++++++++++++++++-
> hw/misc/trace-events | 4 +
> include/hw/misc/aspeed_scu.h | 47 +++++-
> 3 files changed, 351 insertions(+), 6 deletions(-)
>
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 1ac04b6cb0..eb38ea8e19 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -134,6 +134,48 @@
>
> #define AST2600_CLK TO_REG(0x40)
>
> +#define AST2700_SILICON_REV TO_REG(0x00)
> +#define AST2700_HW_STRAP1 TO_REG(0x10)
> +#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
> +#define AST2700_HW_STRAP1_LOCK TO_REG(0x20)
> +#define AST2700_HW_STRAP1_SEC1 TO_REG(0x24)
> +#define AST2700_HW_STRAP1_SEC2 TO_REG(0x28)
> +#define AST2700_HW_STRAP1_SEC3 TO_REG(0x2C)
> +
> +#define AST2700_SCU_CLK_SEL_1 TO_REG(0x280)
> +#define AST2700_SCU_HPLL_PARAM TO_REG(0x300)
> +#define AST2700_SCU_HPLL_EXT_PARAM TO_REG(0x304)
> +#define AST2700_SCU_DPLL_PARAM TO_REG(0x308)
> +#define AST2700_SCU_DPLL_EXT_PARAM TO_REG(0x30c)
> +#define AST2700_SCU_MPLL_PARAM TO_REG(0x310)
> +#define AST2700_SCU_MPLL_EXT_PARAM TO_REG(0x314)
> +#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
> +#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
> +#define AST2700_SCU_CRT1CLK_PARAM TO_REG(0x340)
> +#define AST2700_SCU_CRT2CLK_PARAM TO_REG(0x350)
> +#define AST2700_SCU_MPHYCLK_PARAM TO_REG(0x360)
> +#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_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
> +#define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
> +#define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260)
> +#define AST2700_SCUIO_CLK_STOP_CLR_2 TO_REG(0x264)
> +#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
> +#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
> +#define AST2700_SCUIO_HPLL_PARAM TO_REG(0x300)
> +#define AST2700_SCUIO_HPLL_EXT_PARAM TO_REG(0x304)
> +#define AST2700_SCUIO_APLL_PARAM TO_REG(0x310)
> +#define AST2700_SCUIO_APLL_EXT_PARAM TO_REG(0x314)
> +#define AST2700_SCUIO_DPLL_PARAM TO_REG(0x320)
> +#define AST2700_SCUIO_DPLL_EXT_PARAM TO_REG(0x324)
> +#define AST2700_SCUIO_DPLL_PARAM_READ TO_REG(0x328)
> +#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
> +#define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
> +#define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
> +#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
> +
> #define SCU_IO_REGION_SIZE 0x1000
>
> static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
> @@ -244,6 +286,25 @@ static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
> / asc->apb_divider;
> }
>
> +static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
> +{
> + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
> + uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
> +
> + return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
> + / asc->apb_divider;
> +}
> +
> +static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
> +{
> + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
> + uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
> +
> + return hpll /
> + (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
> + / asc->apb_divider;
> +}
> +
> static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
> {
> AspeedSCUState *s = ASPEED_SCU(opaque);
> @@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
>
> switch (reg) {
> case RNG_DATA:
> - /* On hardware, RNG_DATA works regardless of
> + /*
> + * On hardware, RNG_DATA works regardless of
> * the state of the enable bit in RNG_CTRL
> */
> s->regs[RNG_DATA] = aspeed_scu_get_random();
> @@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
> AST2600_A3_SILICON_REV,
> AST1030_A0_SILICON_REV,
> AST1030_A1_SILICON_REV,
> + AST2700_A0_SILICON_REV,
> + AST2720_A0_SILICON_REV,
> + AST2750_A0_SILICON_REV,
> };
>
> bool is_supported_silicon_rev(uint32_t silicon_rev)
> @@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
> .class_init = aspeed_2600_scu_class_init,
> };
>
> +static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
> + unsigned size)
> +{
> + AspeedSCUState *s = ASPEED_SCU(opaque);
> + int reg = TO_REG(offset);
> +
> + if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + return 0;
> + }
> +
> + switch (reg) {
> + default:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + }
> +
> + trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
> + return s->regs[reg];
> +}
> +
> +static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
> + uint64_t data64, unsigned size)
> +{
> + AspeedSCUState *s = ASPEED_SCU(opaque);
> + int reg = TO_REG(offset);
> + /* Truncate here so bitwise operations below behave as expected */
> + uint32_t data = data64;
> +
> + if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + return;
> + }
> +
> + trace_aspeed_ast2700_scu_write(offset, size, data);
> +
> + switch (reg) {
> + default:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Unhandeled write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + break;
> + }
> +
> + s->regs[reg] = data;
> +}
> +
> +static const MemoryRegionOps aspeed_ast2700_scu_ops = {
> + .read = aspeed_ast2700_scu_read,
> + .write = aspeed_ast2700_scu_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid.min_access_size = 1,
> + .valid.max_access_size = 8,
> + .valid.unaligned = false,
> +};
> +
> +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,
> + [AST2700_HW_STRAP1_SEC2] = 0x00000000,
> + [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
> + [AST2700_SCU_HPLL_PARAM] = 0x0000009f,
> + [AST2700_SCU_HPLL_EXT_PARAM] = 0x8000004f,
> + [AST2700_SCU_DPLL_PARAM] = 0x0080009f,
> + [AST2700_SCU_DPLL_EXT_PARAM] = 0x8000004f,
> + [AST2700_SCU_MPLL_PARAM] = 0x00000040,
> + [AST2700_SCU_MPLL_EXT_PARAM] = 0x80000000,
> + [AST2700_SCU_D1CLK_PARAM] = 0x00050002,
> + [AST2700_SCU_D2CLK_PARAM] = 0x00050002,
> + [AST2700_SCU_CRT1CLK_PARAM] = 0x00050002,
> + [AST2700_SCU_CRT2CLK_PARAM] = 0x00050002,
> + [AST2700_SCU_MPHYCLK_PARAM] = 0x0000004c,
> + [AST2700_SCU_FREQ_CNTR] = 0x000375eb,
> + [AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
> + [AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
> +};
> +
> +static void aspeed_ast2700_scu_reset(DeviceState *dev)
> +{
> + AspeedSCUState *s = ASPEED_SCU(dev);
> + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
> +
> + memcpy(s->regs, asc->resets, asc->nr_regs * 4);
> +}
> +
> +static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
> +
> + dc->desc = "ASPEED 2700 System Control Unit";
> + dc->reset = aspeed_ast2700_scu_reset;
> + asc->resets = ast2700_a0_resets;
> + asc->calc_hpll = aspeed_2600_scu_calc_hpll;
> + asc->get_apb = aspeed_2700_scu_get_apb_freq;
> + asc->apb_divider = 4;
> + asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
> + asc->clkin_25Mhz = true;
> + asc->ops = &aspeed_ast2700_scu_ops;
> +}
> +
> +static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
> + unsigned size)
> +{
> + AspeedSCUState *s = ASPEED_SCU(opaque);
> + int reg = TO_REG(offset);
> + if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + return 0;
> + }
> +
> + switch (reg) {
> + default:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + }
> +
> + trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
> + return s->regs[reg];
> +}
> +
> +static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
> + uint64_t data64, unsigned size)
> +{
> + AspeedSCUState *s = ASPEED_SCU(opaque);
> + int reg = TO_REG(offset);
> + /* Truncate here so bitwise operations below behave as expected */
> + uint32_t data = data64;
> + bool updated = false;
> +
> + if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + return;
> + }
> +
> + trace_aspeed_ast2700_scuio_write(offset, size, data);
> +
> + switch (reg) {
> + case AST2700_SCUIO_CLK_STOP_CTL_1:
> + case AST2700_SCUIO_CLK_STOP_CTL_2:
> + s->regs[reg] |= data;
> + updated = true;
> + break;
> + case AST2700_SCUIO_CLK_STOP_CLR_1:
> + case AST2700_SCUIO_CLK_STOP_CLR_2:
> + s->regs[reg - 1] ^= data;
> + updated = true;
> + break;
> + default:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Unhandeled write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + break;
> + }
> +
> + if (!updated) {
> + s->regs[reg] = data;
> + }
> +}
> +
> +static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
> + .read = aspeed_ast2700_scuio_read,
> + .write = aspeed_ast2700_scuio_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid.min_access_size = 1,
> + .valid.max_access_size = 8,
> + .valid.unaligned = false,
> +};
> +
> +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,
> + [AST2700_HW_STRAP1_SEC2] = 0x00000000,
> + [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
> + [AST2700_SCUIO_CLK_STOP_CTL_1] = 0xffff8400,
> + [AST2700_SCUIO_CLK_STOP_CTL_2] = 0x00005f30,
> + [AST2700_SCUIO_CLK_SEL_1] = 0x86900000,
> + [AST2700_SCUIO_CLK_SEL_2] = 0x00400000,
> + [AST2700_SCUIO_HPLL_PARAM] = 0x10000027,
> + [AST2700_SCUIO_HPLL_EXT_PARAM] = 0x80000014,
> + [AST2700_SCUIO_APLL_PARAM] = 0x1000001f,
> + [AST2700_SCUIO_APLL_EXT_PARAM] = 0x8000000f,
> + [AST2700_SCUIO_DPLL_PARAM] = 0x106e42ce,
> + [AST2700_SCUIO_DPLL_EXT_PARAM] = 0x80000167,
> + [AST2700_SCUIO_DPLL_PARAM_READ] = 0x106e42ce,
> + [AST2700_SCUIO_DPLL_EXT_PARAM_READ] = 0x80000167,
> + [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
> + [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
> + [AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2,
> +};
> +
> +static void aspeed_2700_scuio_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
> +
> + dc->desc = "ASPEED 2700 System Control Unit I/O";
> + dc->reset = aspeed_ast2700_scu_reset;
> + asc->resets = ast2700_a0_resets_io;
> + asc->calc_hpll = aspeed_2600_scu_calc_hpll;
> + asc->get_apb = aspeed_2700_scuio_get_apb_freq;
> + asc->apb_divider = 2;
> + asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
> + asc->clkin_25Mhz = true;
> + asc->ops = &aspeed_ast2700_scuio_ops;
> +}
> +
> +static const TypeInfo aspeed_2700_scu_info = {
> + .name = TYPE_ASPEED_2700_SCU,
> + .parent = TYPE_ASPEED_SCU,
> + .instance_size = sizeof(AspeedSCUState),
> + .class_init = aspeed_2700_scu_class_init,
> +};
> +
> +static const TypeInfo aspeed_2700_scuio_info = {
> + .name = TYPE_ASPEED_2700_SCUIO,
> + .parent = TYPE_ASPEED_SCU,
> + .instance_size = sizeof(AspeedSCUState),
> + .class_init = aspeed_2700_scuio_class_init,
> +};
> +
> static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
> [AST2600_SYS_RST_CTRL] = 0xFFC3FED8,
> [AST2600_SYS_RST_CTRL2] = 0x09FFFFFC,
> @@ -841,6 +1143,8 @@ static void aspeed_scu_register_types(void)
> type_register_static(&aspeed_2500_scu_info);
> type_register_static(&aspeed_2600_scu_info);
> type_register_static(&aspeed_1030_scu_info);
> + type_register_static(&aspeed_2700_scu_info);
> + type_register_static(&aspeed_2700_scuio_info);
> }
>
> type_init(aspeed_scu_register_types);
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events
> index 07010a7ea6..5e5cd77420 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -93,6 +93,10 @@ slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED 0x%04x"
> # aspeed_scu.c
> aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> aspeed_scu_read(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_ast2700_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_ast2700_scu_read(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_ast2700_scuio_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> +aspeed_ast2700_scuio_read(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
>
> # mps2-scc.c
> mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
> diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
> index 7cb6018dbc..58db28db45 100644
> --- a/include/hw/misc/aspeed_scu.h
> +++ b/include/hw/misc/aspeed_scu.h
> @@ -19,10 +19,13 @@ OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEED_SCU)
> #define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
> #define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
> #define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600"
> +#define TYPE_ASPEED_2700_SCU TYPE_ASPEED_SCU "-ast2700"
> +#define TYPE_ASPEED_2700_SCUIO TYPE_ASPEED_SCU "io" "-ast2700"
> #define TYPE_ASPEED_1030_SCU TYPE_ASPEED_SCU "-ast1030"
>
> #define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
> #define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
> +#define ASPEED_AST2700_SCU_NR_REGS (0xE20 >> 2)
>
> struct AspeedSCUState {
> /*< private >*/
> @@ -31,7 +34,7 @@ struct AspeedSCUState {
> /*< public >*/
> MemoryRegion iomem;
>
> - uint32_t regs[ASPEED_AST2600_SCU_NR_REGS];
> + uint32_t regs[ASPEED_AST2700_SCU_NR_REGS];
> uint32_t silicon_rev;
> uint32_t hw_strap1;
> uint32_t hw_strap2;
> @@ -48,6 +51,9 @@ struct AspeedSCUState {
> #define AST2600_A3_SILICON_REV 0x05030303U
> #define AST1030_A0_SILICON_REV 0x80000000U
> #define AST1030_A1_SILICON_REV 0x80010000U
> +#define AST2700_A0_SILICON_REV 0x06000103U
> +#define AST2720_A0_SILICON_REV 0x06000203U
> +#define AST2750_A0_SILICON_REV 0x06000003U
>
> #define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04)
>
> @@ -87,7 +93,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
> * 1. 2012/12/29 Ryan Chen Create
> */
>
> -/* SCU08 Clock Selection Register
> +/*
> + * SCU08 Clock Selection Register
> *
> * 31 Enable Video Engine clock dynamic slow down
> * 30:28 Video Engine clock slow down setting
> @@ -109,7 +116,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
> */
> #define SCU_CLK_GET_PCLK_DIV(x) (((x) >> 23) & 0x7)
>
> -/* SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
> +/*
> + * SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
> *
> * 18 H-PLL parameter selection
> * 0: Select H-PLL by strapping resistors
> @@ -127,7 +135,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
> #define SCU_AST2400_H_PLL_BYPASS_EN (0x1 << 17)
> #define SCU_AST2400_H_PLL_OFF (0x1 << 16)
>
> -/* SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
> +/*
> + * SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
> *
> * 21 Enable H-PLL reset
> * 20 Enable H-PLL bypass mode
> @@ -144,7 +153,8 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
> #define SCU_H_PLL_BYPASS_EN (0x1 << 20)
> #define SCU_H_PLL_OFF (0x1 << 19)
>
> -/* SCU70 Hardware Strapping Register definition (for Aspeed AST2400 SOC)
> +/*
> + * SCU70 Hardware Strapping Register definition (for Aspeed AST2400 SOC)
> *
> * 31:29 Software defined strapping registers
> * 28:27 DRAM size setting (for VGA driver use)
> @@ -361,4 +371,31 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
> */
> #define SCU_AST1030_CLK_GET_PCLK_DIV(x) (((x) >> 8) & 0xf)
>
> +/*
> + * SCU280 Clock Selection 1 Register (for Aspeed AST2700 SCUIO)
> + *
> + * 31:29 MHCLK_DIV
> + * 28 Reserved
> + * 27:25 RGMIICLK_DIV
> + * 24 Reserved
> + * 23:21 RMIICLK_DIV
> + * 20:18 PCLK_DIV
> + * 17:14 SDCLK_DIV
> + * 13 SDCLK_SEL
> + * 12 UART13CLK_SEL
> + * 11 UART12CLK_SEL
> + * 10 UART11CLK_SEL
> + * 9 UART10CLK_SEL
> + * 8 UART9CLK_SEL
> + * 7 UART8CLK_SEL
> + * 6 UART7CLK_SEL
> + * 5 UART6CLK_SEL
> + * 4 UARTDBCLK_SEL
> + * 3 UART4CLK_SEL
> + * 2 UART3CLK_SEL
> + * 1 UART2CLK_SEL
> + * 0 UART1CLK_SEL
> + */
> +#define SCUIO_AST2700_CLK_GET_PCLK_DIV(x) (((x) >> 18) & 0x7)
> +
> #endif /* ASPEED_SCU_H */
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 8/9] aspeed: Add an AST2700 eval board
[not found] ` <20240304092934.1953198-9-jamin_lin@aspeedtech.com>
@ 2024-03-04 15:39 ` Cédric Le Goater
2024-03-05 5:08 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 15:39 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
On 3/4/24 10:29, Jamin Lin wrote:
> AST2700 CPU is ARM Cortex-A35 which is 64 bits.
> Add TARGET_AARCH64 to build this machine.
>
> According to the design of ast2700, it has a bootmcu(riscv-32) which
> is used for executing SPL.
> Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.
>
> Currently, qemu not support emulate two CPU architectures
> at the same machine. Therefore, qemu will only support
> to emulate CPU(cortex-a35) side for ast2700
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> hw/arm/aspeed.c | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 8854581ca8..4544026d14 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -178,6 +178,12 @@ struct AspeedMachineState {
> #define AST2600_EVB_HW_STRAP1 0x000000C0
> #define AST2600_EVB_HW_STRAP2 0x00000003
>
> +#ifdef TARGET_AARCH64
> +/* AST2700 evb hardware value */
> +#define AST2700_EVB_HW_STRAP1 0x000000C0
> +#define AST2700_EVB_HW_STRAP2 0x00000003
> +#endif
> +
> /* Tacoma hardware value */
> #define TACOMA_BMC_HW_STRAP1 0x00000000
> #define TACOMA_BMC_HW_STRAP2 0x00000040
> @@ -1588,6 +1594,26 @@ static void aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
> aspeed_machine_class_init_cpus_defaults(mc);
> }
>
> +#ifdef TARGET_AARCH64
> +static void aspeed_machine_ast2700_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)";
> + amc->soc_name = "ast2700-a0";
> + 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;
> + mc->default_ram_size = 1 * GiB;
This seems low. What's the size on real HW ?
Anyhow,
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Thanks,
C.
> + aspeed_machine_class_init_cpus_defaults(mc);
> +}
> +#endif
> +
> static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
> void *data)
> {
> @@ -1711,6 +1737,12 @@ static const TypeInfo aspeed_machine_types[] = {
> .name = MACHINE_TYPE_NAME("ast1030-evb"),
> .parent = TYPE_ASPEED_MACHINE,
> .class_init = aspeed_minibmc_machine_ast1030_evb_class_init,
> +#ifdef TARGET_AARCH64
> + }, {
> + .name = MACHINE_TYPE_NAME("ast2700-evb"),
> + .parent = TYPE_ASPEED_MACHINE,
> + .class_init = aspeed_machine_ast2700_evb_class_init,
> +#endif
> }, {
> .name = TYPE_ASPEED_MACHINE,
> .parent = TYPE_MACHINE,
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 7/9] aspeed/soc: Add AST2700 support
[not found] ` <20240304092934.1953198-8-jamin_lin@aspeedtech.com>
@ 2024-03-04 15:49 ` Cédric Le Goater
2024-03-11 10:31 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 15:49 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
On 3/4/24 10:29, Jamin Lin wrote:
> Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35 CPU).
>
> AST2700 SOC and its interrupt controller are too complex to handle
> in the common Aspeed SoC framework. We introduce a new ast2700
> class with instance_init and realize handlers.
>
> AST2700 is a 64 bits quad core cpus and support 8 watchdog.
> Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8.
> In addition, update AspeedSocState to support scuio, sli, sliio and intc.
>
> Update silicon_rev data type to 64bits from AspeedSoCClass
Why ? It is still 32bits in the models.
The rest looks good.
Thanks,
C.
> and
> add TYPE_ASPEED27X0_SOC machine type.
>
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> hw/arm/aspeed_ast27x0.c | 462 ++++++++++++++++++++++++++++++++++++
> hw/arm/meson.build | 1 +
> include/hw/arm/aspeed_soc.h | 26 +-
> 3 files changed, 486 insertions(+), 3 deletions(-)
> create mode 100644 hw/arm/aspeed_ast27x0.c
>
> diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
> new file mode 100644
> index 0000000000..c120994e5c
> --- /dev/null
> +++ b/hw/arm/aspeed_ast27x0.c
> @@ -0,0 +1,462 @@
> +/*
> + * ASPEED SoC 27x0 family
> + *
> + * Copyright (C) 2024 ASPEED Technology Inc.
> + *
> + * This code is licensed under the GPL version 2 or later. See
> + * the COPYING file in the top-level directory.
> + *
> + * Implementation extracted from the AST2600 and adapted for AST27x0.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/misc/unimp.h"
> +#include "hw/arm/aspeed_soc.h"
> +#include "qemu/module.h"
> +#include "qemu/error-report.h"
> +#include "hw/i2c/aspeed_i2c.h"
> +#include "net/net.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/intc/arm_gicv3.h"
> +#include "qapi/qmp/qlist.h"
> +
> +static const hwaddr aspeed_soc_ast2700_memmap[] = {
> + [ASPEED_DEV_SPI_BOOT] = 0x400000000,
> + [ASPEED_DEV_SRAM] = 0x10000000,
> + [ASPEED_DEV_SDMC] = 0x12C00000,
> + [ASPEED_DEV_SCU] = 0x12C02000,
> + [ASPEED_DEV_SCUIO] = 0x14C02000,
> + [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,
> + [ASPEED_DEV_UART8] = 0X14C33700,
> + [ASPEED_DEV_UART9] = 0X14C33800,
> + [ASPEED_DEV_UART10] = 0X14C33900,
> + [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_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_VIC] = 0x12100000,
> + [ASPEED_DEV_SLI] = 0x12C17000,
> + [ASPEED_DEV_SLIIO] = 0x14C1E000,
> + [ASPEED_GIC_DIST] = 0x12200000,
> + [ASPEED_GIC_REDIST] = 0x12280000,
> +};
> +
> +#define AST2700_MAX_IRQ 288
> +
> +/* 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,
> + [ASPEED_DEV_SDMC] = 0,
> + [ASPEED_DEV_SCU] = 12,
> + [ASPEED_DEV_ADC] = 130,
> + [ASPEED_DEV_XDMA] = 5,
> + [ASPEED_DEV_EMMC] = 15,
> + [ASPEED_DEV_GPIO] = 11,
> + [ASPEED_DEV_GPIO_1_8V] = 130,
> + [ASPEED_DEV_RTC] = 13,
> + [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_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,
> +};
> +
> +static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
> +{
> + Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
> + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> +
> + return qdev_get_gpio_in(a->intc.gic, sc->irqmap[dev]);
> +}
> +
> +static void aspeed_soc_ast2700_init(Object *obj)
> +{
> + Aspeed27x0SoCState *a = ASPEED27X0_SOC(obj);
> + AspeedSoCState *s = ASPEED_SOC(obj);
> + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> + int i;
> + char socname[8];
> + char typename[64];
> +
> + if (sscanf(sc->name, "%7s", socname) != 1) {
> + g_assert_not_reached();
> + }
> +
> + for (i = 0; i < sc->num_cpus; i++) {
> + object_initialize_child(obj, "cpu[*]", &a->cpu[i],
> + aspeed_soc_cpu_type(sc));
> + }
> +
> + object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCU);
> + qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
> + 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);
> +
> + snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
> + object_initialize_child(obj, "fmc", &s->fmc, typename);
> +
> + for (i = 0; i < sc->spis_num; i++) {
> + snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i, socname);
> + object_initialize_child(obj, "spi[*]", &s->spi[i], typename);
> + }
> +
> + snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
> + object_initialize_child(obj, "sdmc", &s->sdmc, typename);
> + object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
> + "ram-size");
> +
> + for (i = 0; i < sc->wdts_num; i++) {
> + snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
> + object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename);
> + }
> +
> + for (i = 0; i < sc->macs_num; i++) {
> + object_initialize_child(obj, "ftgmac100[*]", &s->ftgmac100[i],
> + TYPE_FTGMAC100);
> +
> + object_initialize_child(obj, "mii[*]", &s->mii[i], TYPE_ASPEED_MII);
> + }
> +
> + for (i = 0; i < sc->uarts_num; i++) {
> + object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
> + }
> +
> + 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_INTC);
> +}
> +
> +/*
> + * ASPEED ast2700 has 0xf as cluster ID
> + *
> + * https://developer.arm.com/documentation/ddi0388/e/the-system-control-coprocessors/summary-of-system-control-coprocessor-registers/multiprocessor-affinity-register
> + */
> +static uint64_t aspeed_calc_affinity(int cpu)
> +{
> + return (0x0 << ARM_AFF1_SHIFT) | cpu;
> +}
> +
> +static void aspeed_soc_ast2700_gic(DeviceState *dev, Error **errp)
> +{
> + Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
> + AspeedSoCState *s = ASPEED_SOC(dev);
> + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> + SysBusDevice *gicbusdev;
> + QList *redist_region_count;
> + int i;
> +
> + a->intc.gic = qdev_new(gicv3_class_name());
> + qdev_prop_set_uint32(a->intc.gic, "revision", 3);
> + qdev_prop_set_uint32(a->intc.gic, "num-cpu", sc->num_cpus);
> + qdev_prop_set_uint32(a->intc.gic, "num-irq", AST2700_MAX_IRQ);
> +
> + redist_region_count = qlist_new();
> + qlist_append_int(redist_region_count, sc->num_cpus);
> + qdev_prop_set_array(a->intc.gic, "redist-region-count",
> + redist_region_count);
> +
> + gicbusdev = SYS_BUS_DEVICE(a->intc.gic);
> + sysbus_realize_and_unref(gicbusdev, errp);
> + sysbus_mmio_map(gicbusdev, 0, sc->memmap[ASPEED_GIC_DIST]);
> + sysbus_mmio_map(gicbusdev, 1, sc->memmap[ASPEED_GIC_REDIST]);
> +
> + for (i = 0; i < sc->num_cpus; i++) {
> + DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
> + int NUM_IRQS = 256, ARCH_GIC_MAINT_IRQ = 9, VIRTUAL_PMU_IRQ = 7;
> + int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
> +
> + const int timer_irq[] = {
> + [GTIMER_PHYS] = 14,
> + [GTIMER_VIRT] = 11,
> + [GTIMER_HYP] = 10,
> + [GTIMER_SEC] = 13,
> + };
> + int j;
> +
> + for (j = 0; j < ARRAY_SIZE(timer_irq); j++) {
> + qdev_connect_gpio_out(cpudev, j,
> + qdev_get_gpio_in(a->intc.gic, ppibase + timer_irq[j]));
> + }
> +
> + qemu_irq irq = qdev_get_gpio_in(a->intc.gic,
> + ppibase + ARCH_GIC_MAINT_IRQ);
> + qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
> + 0, irq);
> + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
> + qdev_get_gpio_in(a->intc.gic, ppibase + VIRTUAL_PMU_IRQ));
> +
> + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
> + sysbus_connect_irq(gicbusdev, i + sc->num_cpus,
> + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
> + sysbus_connect_irq(gicbusdev, i + 2 * sc->num_cpus,
> + 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));
> + }
> +}
> +
> +static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
> +{
> + int i;
> + Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
> + AspeedSoCState *s = ASPEED_SOC(dev);
> + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> + g_autofree char *sram_name = NULL;
> +
> + /* Default boot region (SPI memory or ROMs) */
> + memory_region_init(&s->spi_boot_container, OBJECT(s),
> + "aspeed.spi_boot_container", 0x400000000);
> + memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SPI_BOOT],
> + &s->spi_boot_container);
> +
> + /* CPU */
> + for (i = 0; i < sc->num_cpus; i++) {
> + object_property_set_int(OBJECT(&a->cpu[i]), "mp-affinity",
> + aspeed_calc_affinity(i), &error_abort);
> +
> + object_property_set_int(OBJECT(&a->cpu[i]), "cntfrq", 1125000000,
> + &error_abort);
> + object_property_set_link(OBJECT(&a->cpu[i]), "memory",
> + OBJECT(s->memory), &error_abort);
> +
> + if (!qdev_realize(DEVICE(&a->cpu[i]), NULL, errp)) {
> + return;
> + }
> + }
> +
> + /* GIC */
> + aspeed_soc_ast2700_gic(dev, errp);
> +
> + /* INTC */
> + if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc), errp)) {
> + return;
> + }
> +
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0, sc->memmap[ASPEED_DEV_VIC]);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), 0,
> + qdev_get_gpio_in(DEVICE(&a->cpu), ARM_CPU_IRQ));
> + sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), 1,
> + qdev_get_gpio_in(DEVICE(&a->cpu), ARM_CPU_FIQ));
> +
> + /* SRAM */
> + sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&a->cpu[0])->cpu_index);
> + if (!memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size,
> + errp)) {
> + return;
> + }
> + memory_region_add_subregion(s->memory,
> + sc->memmap[ASPEED_DEV_SRAM], &s->sram);
> +
> + /* SCU */
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
> +
> + /* SCU1 */
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scuio), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scuio), 0,
> + sc->memmap[ASPEED_DEV_SCUIO]);
> +
> + /* UART */
> + if (!aspeed_soc_uart_realize(s, errp)) {
> + return;
> + }
> +
> + /* FMC, The number of CS is set at the board level */
> + object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr),
> + &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 1,
> + ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
> + aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
> +
> + /* Set up an alias on the FMC CE0 region (boot default) */
> + MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
> + memory_region_init_alias(&s->spi_boot, OBJECT(s), "aspeed.spi_boot",
> + fmc0_mmio, 0, memory_region_size(fmc0_mmio));
> + memory_region_add_subregion(&s->spi_boot_container, 0x0, &s->spi_boot);
> +
> + /* SPI */
> + for (i = 0; i < sc->spis_num; i++) {
> + object_property_set_link(OBJECT(&s->spi[i]), "dram",
> + OBJECT(s->dram_mr), &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 0,
> + sc->memmap[ASPEED_DEV_SPI0 + i]);
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 1,
> + ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
> + }
> +
> + /* SDMC - SDRAM Memory Controller */
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdmc), 0,
> + sc->memmap[ASPEED_DEV_SDMC]);
> +
> + /* RAM */
> + if (!aspeed_soc_dram_init(s, errp)) {
> + return;
> + }
> +
> + for (i = 0; i < sc->macs_num; i++) {
> + object_property_set_bool(OBJECT(&s->ftgmac100[i]), "aspeed", true,
> + &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
> + sc->memmap[ASPEED_DEV_ETH1 + i]);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
> + aspeed_soc_get_irq(s, ASPEED_DEV_ETH1 + i));
> +
> + object_property_set_link(OBJECT(&s->mii[i]), "nic",
> + OBJECT(&s->ftgmac100[i]), &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mii[i]), errp)) {
> + return;
> + }
> +
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->mii[i]), 0,
> + sc->memmap[ASPEED_DEV_MII1 + i]);
> + }
> +
> + /* Watch dog */
> + for (i = 0; i < sc->wdts_num; i++) {
> + AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
> + hwaddr wdt_offset = sc->memmap[ASPEED_DEV_WDT] + i * awc->iosize;
> +
> + object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu),
> + &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
> + }
> +
> + /* SLI */
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sli), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sli), 0, sc->memmap[ASPEED_DEV_SLI]);
> +
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sliio), errp)) {
> + return;
> + }
> + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sliio), 0,
> + sc->memmap[ASPEED_DEV_SLIIO]);
> +
> + create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000);
> + create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000);
> + create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000);
> + create_unimplemented_device("ast2700.ltpi", 0x30000000, 0x1000000);
> + create_unimplemented_device("ast2700.io", 0x0, 0x4000000);
> +}
> +
> +static void aspeed_soc_ast2700_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);
> +
> + 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;
> + sc->spis_num = 3;
> + sc->wdts_num = 8;
> + sc->macs_num = 1;
> + sc->uarts_num = 13;
> + sc->num_cpus = 4;
> + sc->uarts_base = ASPEED_DEV_UART0;
> + sc->irqmap = aspeed_soc_ast2700_irqmap;
> + sc->memmap = aspeed_soc_ast2700_memmap;
> + sc->get_irq = aspeed_soc_ast2700_get_irq;
> +}
> +
> +static const TypeInfo aspeed_soc_ast27x0_types[] = {
> + {
> + .name = TYPE_ASPEED27X0_SOC,
> + .parent = TYPE_ASPEED_SOC,
> + .instance_size = sizeof(Aspeed27x0SoCState),
> + .abstract = true,
> + }, {
> + .name = "ast2700-a0",
> + .parent = TYPE_ASPEED27X0_SOC,
> + .instance_init = aspeed_soc_ast2700_init,
> + .class_init = aspeed_soc_ast2700_class_init,
> + },
> +};
> +
> +DEFINE_TYPES(aspeed_soc_ast27x0_types)
> diff --git a/hw/arm/meson.build b/hw/arm/meson.build
> index 6808135c1f..1e3295a423 100644
> --- a/hw/arm/meson.build
> +++ b/hw/arm/meson.build
> @@ -46,6 +46,7 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
> 'aspeed_soc_common.c',
> 'aspeed_ast2400.c',
> 'aspeed_ast2600.c',
> + 'aspeed_ast27x0.c',
> 'aspeed_ast10x0.c',
> 'aspeed_eeprom.c',
> 'fby35.c'))
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index c60fac900a..fab5abff9e 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -26,6 +26,7 @@
> #include "hw/ssi/aspeed_smc.h"
> #include "hw/misc/aspeed_hace.h"
> #include "hw/misc/aspeed_sbc.h"
> +#include "hw/misc/aspeed_sli.h"
> #include "hw/watchdog/wdt_aspeed.h"
> #include "hw/net/ftgmac100.h"
> #include "target/arm/cpu.h"
> @@ -41,8 +42,8 @@
>
> #define ASPEED_SPIS_NUM 2
> #define ASPEED_EHCIS_NUM 2
> -#define ASPEED_WDTS_NUM 4
> -#define ASPEED_CPUS_NUM 2
> +#define ASPEED_WDTS_NUM 8
> +#define ASPEED_CPUS_NUM 4
> #define ASPEED_MACS_NUM 4
> #define ASPEED_UARTS_NUM 13
> #define ASPEED_JTAG_NUM 2
> @@ -61,6 +62,7 @@ struct AspeedSoCState {
> AspeedI2CState i2c;
> AspeedI3CState i3c;
> AspeedSCUState scu;
> + AspeedSCUState scuio;
> AspeedHACEState hace;
> AspeedXDMAState xdma;
> AspeedADCState adc;
> @@ -68,6 +70,8 @@ struct AspeedSoCState {
> AspeedSMCState spi[ASPEED_SPIS_NUM];
> EHCISysBusState ehci[ASPEED_EHCIS_NUM];
> AspeedSBCState sbc;
> + AspeedSLIState sli;
> + AspeedSLIState sliio;
> MemoryRegion secsram;
> UnimplementedDeviceState sbc_unimplemented;
> AspeedSDMCState sdmc;
> @@ -117,6 +121,16 @@ struct Aspeed2600SoCState {
> #define TYPE_ASPEED2600_SOC "aspeed2600-soc"
> OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2600SoCState, ASPEED2600_SOC)
>
> +struct Aspeed27x0SoCState {
> + AspeedSoCState parent;
> +
> + ARMCPU cpu[ASPEED_CPUS_NUM];
> + AspeedINTCState intc;
> +};
> +
> +#define TYPE_ASPEED27X0_SOC "aspeed27x0-soc"
> +OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0SoCState, ASPEED27X0_SOC)
> +
> struct Aspeed10x0SoCState {
> AspeedSoCState parent;
>
> @@ -132,7 +146,7 @@ struct AspeedSoCClass {
> const char *name;
> /** valid_cpu_types: NULL terminated array of a single CPU type. */
> const char * const *valid_cpu_types;
> - uint32_t silicon_rev;
> + uint64_t silicon_rev;
> uint64_t sram_size;
> uint64_t secsram_size;
> int spis_num;
> @@ -168,6 +182,7 @@ enum {
> ASPEED_DEV_UART13,
> ASPEED_DEV_VUART,
> ASPEED_DEV_FMC,
> + ASPEED_DEV_SPI0,
> ASPEED_DEV_SPI1,
> ASPEED_DEV_SPI2,
> ASPEED_DEV_EHCI1,
> @@ -222,6 +237,11 @@ enum {
> ASPEED_DEV_JTAG1,
> ASPEED_DEV_FSI1,
> ASPEED_DEV_FSI2,
> + ASPEED_DEV_SCUIO,
> + ASPEED_DEV_SLI,
> + ASPEED_DEV_SLIIO,
> + ASPEED_GIC_DIST,
> + ASPEED_GIC_REDIST,
> };
>
> qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 0/9] Add AST2700 support
2024-03-04 9:29 [PATCH v2 0/9] Add AST2700 support Jamin Lin via
` (7 preceding siblings ...)
[not found] ` <20240304092934.1953198-8-jamin_lin@aspeedtech.com>
@ 2024-03-04 15:54 ` Cédric Le Goater
2024-03-05 3:38 ` Jamin Lin
8 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-04 15:54 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: troy_lee, yunlin.tang
Hello Jamin,
On 3/4/24 10:29, Jamin Lin wrote:
> Changes from v1:
> The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC.
>
> Changes from v2:
> - replace is_aarch64 with is_bus64bit for sdmc patch review.
> - fix incorrect dram size for AST2700
>
> Test steps:
> 1. Download openbmc image for AST2700 from
> https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.00
> https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.00/
> ast2700-default-obmc.tar.gz
> 2. untar ast2700-default-obmc.tar.gz
> ```
> tar -xf ast2700-default-obmc.tar.gz
> ```
> 3. Run and the contents of scripts as following
> IMGDIR=ast2700-default
> UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
> UBOOT_DTB_ADDR=$((0x400000000 + ${UBOOT_SIZE}))
>
> qemu-system-aarch64 -M ast2700-evb -nographic\
> -device loader,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\
> -device loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\
> -device loader,addr=0x430000000,file=${IMGDIR}/bl31.bin,force-raw=on\
> -device loader,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
> -device loader,addr=0x430000000,cpu-num=0\
> -device loader,addr=0x430000000,cpu-num=1\
> -device loader,addr=0x430000000,cpu-num=2\
> -device loader,addr=0x430000000,cpu-num=3\
> -smp 4\
> -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
> -serial mon:stdio\
> -snapshot
>
> Known Issue:
> 1. QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
> but not support Shared Peripheral Interrupt (SPI), yet.
> Added work around in INTC patch to set GICINT132[18]
> which was BMC UART interrupt if it received GICINT132, so users are
> able to type any key from keyboard to trigger GICINT132 interrupt
> until AST2700 boot into login prompt. It is a temporary solution.
> If users encounter boot stck and no booting log,
> please type any key from keyboard.
I haven't looked at the GIC issue but I started reviewing what I
received.
The mailer issue needs to be fixed before we consider this patches
for merge. May be use an external email while keeping the same
From: and Signed-off-by address.
When you resend, could you please add an avocado test ?
Thanks,
C.
> Jamin Lin (9):
> aspeed/wdt: Add AST2700 support
> aspeed/sli: Add AST2700 support
> aspeed/sdmc: Add AST2700 support
> aspeed/smc: Add AST2700 support
> aspeed/scu: Add AST2700 support
> aspeed/intc: Add AST2700 support
> aspeed/soc: Add AST2700 support
> aspeed: Add an AST2700 eval board
> aspeed/soc: fix incorrect dram size for AST2700
>
> hw/arm/aspeed.c | 32 ++
> hw/arm/aspeed_ast27x0.c | 554 +++++++++++++++++++++++++++++++
> hw/arm/meson.build | 1 +
> hw/intc/aspeed_intc.c | 135 ++++++++
> hw/intc/meson.build | 1 +
> hw/misc/aspeed_scu.c | 306 ++++++++++++++++-
> hw/misc/aspeed_sdmc.c | 215 ++++++++++--
> hw/misc/aspeed_sli.c | 179 ++++++++++
> hw/misc/meson.build | 3 +-
> hw/misc/trace-events | 11 +
> hw/ssi/aspeed_smc.c | 326 ++++++++++++++++--
> hw/ssi/trace-events | 2 +-
> hw/watchdog/wdt_aspeed.c | 24 ++
> include/hw/arm/aspeed_soc.h | 27 +-
> include/hw/intc/aspeed_vic.h | 29 ++
> include/hw/misc/aspeed_scu.h | 47 ++-
> include/hw/misc/aspeed_sdmc.h | 4 +-
> include/hw/misc/aspeed_sli.h | 32 ++
> include/hw/ssi/aspeed_smc.h | 1 +
> include/hw/watchdog/wdt_aspeed.h | 3 +-
> 20 files changed, 1880 insertions(+), 52 deletions(-)
> create mode 100644 hw/arm/aspeed_ast27x0.c
> create mode 100644 hw/intc/aspeed_intc.c
> create mode 100644 hw/misc/aspeed_sli.c
> create mode 100644 include/hw/misc/aspeed_sli.h
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 1/9] aspeed/wdt: Add AST2700 support
2024-03-04 14:32 ` [PATCH v2 1/9] aspeed/wdt: " Cédric Le Goater
@ 2024-03-05 3:08 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-05 3:08 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 10:32 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 1/9] aspeed/wdt: Add AST2700 support
>
> Hello Jamin,
>
> On 3/4/24 10:29, Jamin Lin wrote:
> > AST2700 wdt controller is similiar to AST2600's wdt, but the AST2700
> > has 8 watchdogs, and they each have a 0x80 of registers.
>
> ... they each have 0x80 registers.
>
> > Introduce ast2700 object class and increse the number of regs(offset)
> > of
>
> .. increase ...
>
> > ast2700 model.
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
>
Thanks for review and typo will be fixed in V3 patch series.
Jamin
>
> Reviewed-by: Cédric Le Goater <clg@kaod.org>
>
> Thanks,
>
> C.
>
>
> > ---
> > hw/watchdog/wdt_aspeed.c | 24 ++++++++++++++++++++++++
> > include/hw/watchdog/wdt_aspeed.h | 3 ++-
> > 2 files changed, 26 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c index
> > d70b656f8e..75685c5647 100644
> > --- a/hw/watchdog/wdt_aspeed.c
> > +++ b/hw/watchdog/wdt_aspeed.c
> > @@ -422,12 +422,36 @@ static const TypeInfo aspeed_1030_wdt_info = {
> > .class_init = aspeed_1030_wdt_class_init,
> > };
> >
> > +static void aspeed_2700_wdt_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
> > +
> > + dc->desc = "ASPEED 2700 Watchdog Controller";
> > + awc->iosize = 0x80;
> > + awc->ext_pulse_width_mask = 0xfffff; /* TODO */
> > + awc->reset_ctrl_reg = AST2600_SCU_RESET_CONTROL1;
> > + awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
> > + awc->wdt_reload = aspeed_wdt_reload_1mhz;
> > + awc->sanitize_ctrl = aspeed_2600_sanitize_ctrl;
> > + awc->default_status = 0x014FB180;
> > + awc->default_reload_value = 0x014FB180; }
> > +
> > +static const TypeInfo aspeed_2700_wdt_info = {
> > + .name = TYPE_ASPEED_2700_WDT,
> > + .parent = TYPE_ASPEED_WDT,
> > + .instance_size = sizeof(AspeedWDTState),
> > + .class_init = aspeed_2700_wdt_class_init, };
> > +
> > static void wdt_aspeed_register_types(void)
> > {
> > type_register_static(&aspeed_wdt_info);
> > type_register_static(&aspeed_2400_wdt_info);
> > type_register_static(&aspeed_2500_wdt_info);
> > type_register_static(&aspeed_2600_wdt_info);
> > + type_register_static(&aspeed_2700_wdt_info);
> > type_register_static(&aspeed_1030_wdt_info);
> > }
> >
> > diff --git a/include/hw/watchdog/wdt_aspeed.h
> > b/include/hw/watchdog/wdt_aspeed.h
> > index e90ef86651..830b0a7936 100644
> > --- a/include/hw/watchdog/wdt_aspeed.h
> > +++ b/include/hw/watchdog/wdt_aspeed.h
> > @@ -19,9 +19,10 @@ OBJECT_DECLARE_TYPE(AspeedWDTState,
> AspeedWDTClass, ASPEED_WDT)
> > #define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
> > #define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
> > #define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600"
> > +#define TYPE_ASPEED_2700_WDT TYPE_ASPEED_WDT "-ast2700"
> > #define TYPE_ASPEED_1030_WDT TYPE_ASPEED_WDT "-ast1030"
> >
> > -#define ASPEED_WDT_REGS_MAX (0x30 / 4)
> > +#define ASPEED_WDT_REGS_MAX (0x80 / 4)
> >
> > struct AspeedWDTState {
> > /*< private >*/
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 2/9] aspeed/sli: Add AST2700 support
2024-03-04 14:36 ` [PATCH v2 2/9] aspeed/sli: " Cédric Le Goater
@ 2024-03-05 3:28 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-05 3:28 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 10:36 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 2/9] aspeed/sli: Add AST2700 support
>
> On 3/4/24 10:29, Jamin Lin wrote:
> > AST2700 SLI engine is designed to accelerate the throughput between
> > cross-die connections.
> > It have CPU_SLI at CPU die and IO_SLI at IO die.
> >
> > Introduce new ast2700_sli and ast2700_sliio class with instance_init
> > and realize handlers.
>
> This should say that the implementation is a dummy one.
Will fix
>
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> > hw/misc/aspeed_sli.c | 179
> +++++++++++++++++++++++++++++++++++
> > hw/misc/meson.build | 3 +-
> > hw/misc/trace-events | 7 ++
> > include/hw/misc/aspeed_sli.h | 32 +++++++
> > 4 files changed, 220 insertions(+), 1 deletion(-)
> > create mode 100644 hw/misc/aspeed_sli.c
> > create mode 100644 include/hw/misc/aspeed_sli.h
> >
> > diff --git a/hw/misc/aspeed_sli.c b/hw/misc/aspeed_sli.c new file mode
> > 100644 index 0000000000..4af42f145c
> > --- /dev/null
> > +++ b/hw/misc/aspeed_sli.c
> > @@ -0,0 +1,179 @@
> > +/*
> > + * ASPEED SLI Controller
> > + *
> > + * Copyright (C) 2024 ASPEED Technology Inc.
> > + *
> > + * This code is licensed under the GPL version 2 or later. See
> > + * the COPYING file in the top-level directory.
>
> In all files, the paragraph above can be replaced with :
>
> * SPDX-License-Identifier: GPL-2.0-or-later
>
Will fix
>
> Thanks,
>
> C.
>
Thanks for review and they will be fixed in V3 patch series.
Jamin
>
>
>
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/log.h"
> > +#include "qemu/error-report.h"
> > +#include "hw/qdev-properties.h"
> > +#include "hw/misc/aspeed_sli.h"
> > +#include "qapi/error.h"
> > +#include "migration/vmstate.h"
> > +#include "trace.h"
> > +
> > +#define SLI_REGION_SIZE 0x500
> > +#define TO_REG(addr) ((addr) >> 2)
> > +
> > +static uint64_t aspeed_sli_read(void *opaque, hwaddr addr, unsigned
> > +int size) {
> > + AspeedSLIState *s = ASPEED_SLI(opaque);
> > + int reg = TO_REG(addr);
> > +
> > + if (reg >= ARRAY_SIZE(s->regs)) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: Out-of-bounds read at offset 0x%"
> HWADDR_PRIx "\n",
> > + __func__, addr);
> > + return 0;
> > + }
> > +
> > + trace_aspeed_sli_read(addr, size, s->regs[reg]);
> > + return s->regs[reg];
> > +}
> > +
> > +static void aspeed_sli_write(void *opaque, hwaddr addr, uint64_t data,
> > + unsigned int size) {
> > + AspeedSLIState *s = ASPEED_SLI(opaque);
> > + int reg = TO_REG(addr);
> > +
> > + if (reg >= ARRAY_SIZE(s->regs)) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: Out-of-bounds write at offset 0x%"
> HWADDR_PRIx "\n",
> > + __func__, addr);
> > + return;
> > + }
> > +
> > + trace_aspeed_sli_write(addr, size, data);
> > + s->regs[reg] = data;
> > +}
> > +
> > +static uint64_t aspeed_sliio_read(void *opaque, hwaddr addr, unsigned
> > +int size) {
> > + AspeedSLIState *s = ASPEED_SLI(opaque);
> > + int reg = TO_REG(addr);
> > +
> > + if (reg >= ARRAY_SIZE(s->regs)) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: Out-of-bounds read at offset 0x%"
> HWADDR_PRIx "\n",
> > + __func__, addr);
> > + return 0;
> > + }
> > +
> > + trace_aspeed_sliio_read(addr, size, s->regs[reg]);
> > + return s->regs[reg];
> > +}
> > +
> > +static void aspeed_sliio_write(void *opaque, hwaddr addr, uint64_t data,
> > + unsigned int size) {
> > + AspeedSLIState *s = ASPEED_SLI(opaque);
> > + int reg = TO_REG(addr);
> > +
> > + if (reg >= ARRAY_SIZE(s->regs)) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: Out-of-bounds write at offset 0x%"
> HWADDR_PRIx "\n",
> > + __func__, addr);
> > + return;
> > + }
> > +
> > + trace_aspeed_sliio_write(addr, size, data);
> > + s->regs[reg] = data;
> > +}
> > +
> > +static const MemoryRegionOps aspeed_sli_ops = {
> > + .read = aspeed_sli_read,
> > + .write = aspeed_sli_write,
> > + .endianness = DEVICE_LITTLE_ENDIAN,
> > + .valid = {
> > + .min_access_size = 1,
> > + .max_access_size = 4,
> > + },
> > +};
> > +
> > +static const MemoryRegionOps aspeed_sliio_ops = {
> > + .read = aspeed_sliio_read,
> > + .write = aspeed_sliio_write,
> > + .endianness = DEVICE_LITTLE_ENDIAN,
> > + .valid = {
> > + .min_access_size = 1,
> > + .max_access_size = 4,
> > + },
> > +};
> > +
> > +static void aspeed_sli_realize(DeviceState *dev, Error **errp) {
> > + AspeedSLIState *s = ASPEED_SLI(dev);
> > + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > +
> > + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sli_ops, s,
> > + TYPE_ASPEED_SLI, SLI_REGION_SIZE);
> > + sysbus_init_mmio(sbd, &s->iomem); }
> > +
> > +static void aspeed_sliio_realize(DeviceState *dev, Error **errp) {
> > + AspeedSLIState *s = ASPEED_SLI(dev);
> > + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > +
> > + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sliio_ops, s,
> > + TYPE_ASPEED_SLI, SLI_REGION_SIZE);
> > + sysbus_init_mmio(sbd, &s->iomem); }
> > +
> > +static void aspeed_sli_class_init(ObjectClass *klass, void *data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > + dc->desc = "Aspeed SLI Controller";
> > + dc->realize = aspeed_sli_realize; }
> > +
> > +static const TypeInfo aspeed_sli_info = {
> > + .name = TYPE_ASPEED_SLI,
> > + .parent = TYPE_SYS_BUS_DEVICE,
> > + .instance_size = sizeof(AspeedSLIState),
> > + .class_init = aspeed_sli_class_init,
> > + .class_size = sizeof(AspeedSLIClass),
> > + .abstract = true,
> > +};
> > +
> > +static void aspeed_2700_sli_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > + dc->desc = "AST2700 SLI Controller"; }
> > +
> > +static void aspeed_2700_sliio_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > + dc->desc = "AST2700 I/O SLI Controller";
> > + dc->realize = aspeed_sliio_realize; }
> > +
> > +static const TypeInfo aspeed_2700_sli_info = {
> > + .name = TYPE_ASPEED_2700_SLI,
> > + .parent = TYPE_ASPEED_SLI,
> > + .class_init = aspeed_2700_sli_class_init,
> > +};
> > +
> > +static const TypeInfo aspeed_2700_sliio_info = {
> > + .name = TYPE_ASPEED_2700_SLIIO,
> > + .parent = TYPE_ASPEED_SLI,
> > + .class_init = aspeed_2700_sliio_class_init,
> > +};
> > +
> > +static void aspeed_sli_register_types(void) {
> > + type_register_static(&aspeed_sli_info);
> > + type_register_static(&aspeed_2700_sli_info);
> > + type_register_static(&aspeed_2700_sliio_info);
> > +}
> > +
> > +type_init(aspeed_sli_register_types);
> > diff --git a/hw/misc/meson.build b/hw/misc/meson.build index
> > 746686835b..790f05525a 100644
> > --- a/hw/misc/meson.build
> > +++ b/hw/misc/meson.build
> > @@ -137,7 +137,8 @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true:
> files(
> > 'aspeed_sbc.c',
> > 'aspeed_sdmc.c',
> > 'aspeed_xdma.c',
> > - 'aspeed_peci.c'))
> > + 'aspeed_peci.c',
> > + 'aspeed_sli.c'))
> >
> > system_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
> > system_ss.add(when: 'CONFIG_NRF51_SOC', if_true:
> > files('nrf51_rng.c')) diff --git a/hw/misc/trace-events
> > b/hw/misc/trace-events index 5f5bc92222..07010a7ea6 100644
> > --- a/hw/misc/trace-events
> > +++ b/hw/misc/trace-events
> > @@ -341,3 +341,10 @@ djmemc_write(int reg, uint64_t value, unsigned int
> size) "reg=0x%x value=0x%"PRI
> > # iosb.c
> > iosb_read(int reg, uint64_t value, unsigned int size) "reg=0x%x
> value=0x%"PRIx64" size=%u"
> > iosb_write(int reg, uint64_t value, unsigned int size) "reg=0x%x
> value=0x%"PRIx64" size=%u"
> > +
> > +# aspeed_sli.c
> > +aspeed_sli_write(uint64_t offset, unsigned int size, uint32_t data)
> > +"To 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_sli_read(uint64_t
> > +offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size
> > +%u: 0x%" PRIx32 aspeed_sliio_write(uint64_t offset, unsigned int
> > +size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> > +aspeed_sliio_read(uint64_t offset, unsigned int size, uint32_t data)
> > +"To 0x%" PRIx64 " of size %u: 0x%" PRIx32
> > +
> > diff --git a/include/hw/misc/aspeed_sli.h
> > b/include/hw/misc/aspeed_sli.h new file mode 100644 index
> > 0000000000..15892950e2
> > --- /dev/null
> > +++ b/include/hw/misc/aspeed_sli.h
> > @@ -0,0 +1,32 @@
> > +/*
> > + * ASPEED SLI Controller
> > + *
> > + * Copyright (C) 2024 ASPEED Technology Inc.
> > + *
> > + * This code is licensed under the GPL version 2 or later. See
> > + * the COPYING file in the top-level directory.
> > + */
> > +#ifndef ASPEED_SLI_H
> > +#define ASPEED_SLI_H
> > +
> > +#include "hw/sysbus.h"
> > +
> > +#define TYPE_ASPEED_SLI "aspeed.sli"
> > +#define TYPE_ASPEED_2700_SLI TYPE_ASPEED_SLI "-ast2700"
> > +#define TYPE_ASPEED_2700_SLIIO TYPE_ASPEED_SLI "io" "-ast2700"
> > +OBJECT_DECLARE_TYPE(AspeedSLIState, AspeedSLIClass, ASPEED_SLI)
> > +
> > +#define ASPEED_SLI_NR_REGS (0x500 >> 2)
> > +
> > +struct AspeedSLIState {
> > + SysBusDevice parent;
> > + MemoryRegion iomem;
> > +
> > + uint32_t regs[ASPEED_SLI_NR_REGS]; };
> > +
> > +struct AspeedSLIClass {
> > + SysBusDeviceClass parent_class;
> > +};
> > +
> > +#endif /* ASPEED_SLI_H */
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 0/9] Add AST2700 support
2024-03-04 15:54 ` [PATCH v2 0/9] " Cédric Le Goater
@ 2024-03-05 3:38 ` Jamin Lin
2024-03-07 10:42 ` Cédric Le Goater
0 siblings, 1 reply; 24+ messages in thread
From: Jamin Lin @ 2024-03-05 3:38 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 11:54 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 0/9] Add AST2700 support
>
> Hello Jamin,
>
> On 3/4/24 10:29, Jamin Lin wrote:
> > Changes from v1:
> > The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700
> SoC.
> >
> > Changes from v2:
> > - replace is_aarch64 with is_bus64bit for sdmc patch review.
> > - fix incorrect dram size for AST2700
> >
> > Test steps:
> > 1. Download openbmc image for AST2700 from
> > https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.00
> >
> https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.00/
> > ast2700-default-obmc.tar.gz
> > 2. untar ast2700-default-obmc.tar.gz
> > ```
> > tar -xf ast2700-default-obmc.tar.gz
> > ```
> > 3. Run and the contents of scripts as following IMGDIR=ast2700-default
> > UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
> > UBOOT_DTB_ADDR=$((0x400000000 + ${UBOOT_SIZE}))
> >
> > qemu-system-aarch64 -M ast2700-evb -nographic\
> > -device
> loader,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\
> > -device
> loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\
> > -device loader,addr=0x430000000,file=${IMGDIR}/bl31.bin,force-raw=on\
> > -device
> loader,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
> > -device loader,addr=0x430000000,cpu-num=0\
> > -device loader,addr=0x430000000,cpu-num=1\
> > -device loader,addr=0x430000000,cpu-num=2\
> > -device loader,addr=0x430000000,cpu-num=3\
> > -smp 4\
> > -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
> > -serial mon:stdio\
> > -snapshot
> >
> > Known Issue:
> > 1. QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
> > but not support Shared Peripheral Interrupt (SPI), yet.
> > Added work around in INTC patch to set GICINT132[18] which was BMC
> > UART interrupt if it received GICINT132, so users are able to type any
> > key from keyboard to trigger GICINT132 interrupt until AST2700 boot
> > into login prompt. It is a temporary solution.
> > If users encounter boot stck and no booting log, please type any key
> > from keyboard.
>
> I haven't looked at the GIC issue but I started reviewing what I received.
>
> The mailer issue needs to be fixed before we consider this patches for merge.
> May be use an external email while keeping the same
> From: and Signed-off-by address.
>
Understand.
Thanks for your suggestion. I am asking our IT help to fix our smtp server issue.
They are fixing it. I will use my external account to send V3 patch series if
this issues does not be fixed, yet.
> When you resend, could you please add an avocado test ?
>
Sure, will create a patch for avocado test.
Thanks
> Thanks,
>
> C.
>
>
> > Jamin Lin (9):
> > aspeed/wdt: Add AST2700 support
> > aspeed/sli: Add AST2700 support
> > aspeed/sdmc: Add AST2700 support
> > aspeed/smc: Add AST2700 support
> > aspeed/scu: Add AST2700 support
> > aspeed/intc: Add AST2700 support
> > aspeed/soc: Add AST2700 support
> > aspeed: Add an AST2700 eval board
> > aspeed/soc: fix incorrect dram size for AST2700
> >
> > hw/arm/aspeed.c | 32 ++
> > hw/arm/aspeed_ast27x0.c | 554
> +++++++++++++++++++++++++++++++
> > hw/arm/meson.build | 1 +
> > hw/intc/aspeed_intc.c | 135 ++++++++
> > hw/intc/meson.build | 1 +
> > hw/misc/aspeed_scu.c | 306 ++++++++++++++++-
> > hw/misc/aspeed_sdmc.c | 215 ++++++++++--
> > hw/misc/aspeed_sli.c | 179 ++++++++++
> > hw/misc/meson.build | 3 +-
> > hw/misc/trace-events | 11 +
> > hw/ssi/aspeed_smc.c | 326 ++++++++++++++++--
> > hw/ssi/trace-events | 2 +-
> > hw/watchdog/wdt_aspeed.c | 24 ++
> > include/hw/arm/aspeed_soc.h | 27 +-
> > include/hw/intc/aspeed_vic.h | 29 ++
> > include/hw/misc/aspeed_scu.h | 47 ++-
> > include/hw/misc/aspeed_sdmc.h | 4 +-
> > include/hw/misc/aspeed_sli.h | 32 ++
> > include/hw/ssi/aspeed_smc.h | 1 +
> > include/hw/watchdog/wdt_aspeed.h | 3 +-
> > 20 files changed, 1880 insertions(+), 52 deletions(-)
> > create mode 100644 hw/arm/aspeed_ast27x0.c
> > create mode 100644 hw/intc/aspeed_intc.c
> > create mode 100644 hw/misc/aspeed_sli.c
> > create mode 100644 include/hw/misc/aspeed_sli.h
> >
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 8/9] aspeed: Add an AST2700 eval board
2024-03-04 15:39 ` [PATCH v2 8/9] aspeed: Add an AST2700 eval board Cédric Le Goater
@ 2024-03-05 5:08 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-05 5:08 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 11:40 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 8/9] aspeed: Add an AST2700 eval board
>
> On 3/4/24 10:29, Jamin Lin wrote:
> > AST2700 CPU is ARM Cortex-A35 which is 64 bits.
> > Add TARGET_AARCH64 to build this machine.
> >
> > According to the design of ast2700, it has a bootmcu(riscv-32) which
> > is used for executing SPL.
> > Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.
> >
> > Currently, qemu not support emulate two CPU architectures at the same
> > machine. Therefore, qemu will only support to emulate CPU(cortex-a35)
> > side for ast2700
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> > hw/arm/aspeed.c | 32 ++++++++++++++++++++++++++++++++
> > 1 file changed, 32 insertions(+)
> >
> > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index
> > 8854581ca8..4544026d14 100644
> > --- a/hw/arm/aspeed.c
> > +++ b/hw/arm/aspeed.c
> > @@ -178,6 +178,12 @@ struct AspeedMachineState {
> > #define AST2600_EVB_HW_STRAP1 0x000000C0
> > #define AST2600_EVB_HW_STRAP2 0x00000003
> >
> > +#ifdef TARGET_AARCH64
> > +/* AST2700 evb hardware value */
> > +#define AST2700_EVB_HW_STRAP1 0x000000C0 #define
> > +AST2700_EVB_HW_STRAP2 0x00000003 #endif
> > +
> > /* Tacoma hardware value */
> > #define TACOMA_BMC_HW_STRAP1 0x00000000
> > #define TACOMA_BMC_HW_STRAP2 0x00000040 @@ -1588,6
> +1594,26 @@
> > static void aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass
> *oc,
> > aspeed_machine_class_init_cpus_defaults(mc);
> > }
> >
> > +#ifdef TARGET_AARCH64
> > +static void aspeed_machine_ast2700_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)";
> > + amc->soc_name = "ast2700-a0";
> > + 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;
> > + mc->default_ram_size = 1 * GiB;
>
> This seems low. What's the size on real HW ?
>
Hi Cedric,
Thanks for review.
The default ram size is 1 GiB on AST2700 EVB and AST2700 support the maximum dram size is 8GiB.
> Anyhow,
>
>
> Reviewed-by: Cédric Le Goater <clg@kaod.org>
>
> Thanks,
>
> C.
>
>
> > + aspeed_machine_class_init_cpus_defaults(mc);
> > +}
> > +#endif
> > +
> > static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass
> *oc,
> > void
> *data)
> > {
> > @@ -1711,6 +1737,12 @@ static const TypeInfo aspeed_machine_types[] = {
> > .name = MACHINE_TYPE_NAME("ast1030-evb"),
> > .parent = TYPE_ASPEED_MACHINE,
> > .class_init =
> aspeed_minibmc_machine_ast1030_evb_class_init,
> > +#ifdef TARGET_AARCH64
> > + }, {
> > + .name = MACHINE_TYPE_NAME("ast2700-evb"),
> > + .parent = TYPE_ASPEED_MACHINE,
> > + .class_init = aspeed_machine_ast2700_evb_class_init,
> > +#endif
> > }, {
> > .name = TYPE_ASPEED_MACHINE,
> > .parent = TYPE_MACHINE,
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 0/9] Add AST2700 support
2024-03-05 3:38 ` Jamin Lin
@ 2024-03-07 10:42 ` Cédric Le Goater
2024-03-11 1:14 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-07 10:42 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
On 3/5/24 04:38, Jamin Lin wrote:
>> -----Original Message-----
>> From: Cédric Le Goater <clg@kaod.org>
>> Sent: Monday, March 4, 2024 11:54 PM
>> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
>> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
>> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
>> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
>> <qemu-devel@nongnu.org>
>> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
>> <yunlin.tang@aspeedtech.com>
>> Subject: Re: [PATCH v2 0/9] Add AST2700 support
>>
>> Hello Jamin,
>>
>> On 3/4/24 10:29, Jamin Lin wrote:
>>> Changes from v1:
>>> The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700
>> SoC.
>>>
>>> Changes from v2:
>>> - replace is_aarch64 with is_bus64bit for sdmc patch review.
>>> - fix incorrect dram size for AST2700
>>>
>>> Test steps:
>>> 1. Download openbmc image for AST2700 from
>>> https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.00
>>>
>> https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.00/
>>> ast2700-default-obmc.tar.gz
>>> 2. untar ast2700-default-obmc.tar.gz
>>> ```
>>> tar -xf ast2700-default-obmc.tar.gz
>>> ```
>>> 3. Run and the contents of scripts as following IMGDIR=ast2700-default
>>> UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
>>> UBOOT_DTB_ADDR=$((0x400000000 + ${UBOOT_SIZE}))
>>>
>>> qemu-system-aarch64 -M ast2700-evb -nographic\
>>> -device
>> loader,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\
>>> -device
>> loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\
>>> -device loader,addr=0x430000000,file=${IMGDIR}/bl31.bin,force-raw=on\
>>> -device
>> loader,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
>>> -device loader,addr=0x430000000,cpu-num=0\
>>> -device loader,addr=0x430000000,cpu-num=1\
>>> -device loader,addr=0x430000000,cpu-num=2\
>>> -device loader,addr=0x430000000,cpu-num=3\
>>> -smp 4\
>>> -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
>>> -serial mon:stdio\
>>> -snapshot
>>>
>>> Known Issue:
>>> 1. QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
>>> but not support Shared Peripheral Interrupt (SPI), yet.
>>> Added work around in INTC patch to set GICINT132[18] which was BMC
>>> UART interrupt if it received GICINT132, so users are able to type any
>>> key from keyboard to trigger GICINT132 interrupt until AST2700 boot
>>> into login prompt. It is a temporary solution.
>>> If users encounter boot stck and no booting log, please type any key
>>> from keyboard.
>>
>> I haven't looked at the GIC issue but I started reviewing what I received.
>>
>> The mailer issue needs to be fixed before we consider this patches for merge.
>> May be use an external email while keeping the same
>> From: and Signed-off-by address.
>>
> Understand.
> Thanks for your suggestion. I am asking our IT help to fix our smtp server issue.
> They are fixing it. I will use my external account to send V3 patch series if
> this issues does not be fixed, yet.
>> When you resend, could you please add an avocado test ?
>>
> Sure, will create a patch for avocado test.
Forgot to add,
please update the documentation docs/system/arm/aspeed.rst.
Thanks,
C.
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 0/9] Add AST2700 support
2024-03-07 10:42 ` Cédric Le Goater
@ 2024-03-11 1:14 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-11 1:14 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Thursday, March 7, 2024 6:43 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 0/9] Add AST2700 support
>
> On 3/5/24 04:38, Jamin Lin wrote:
> >> -----Original Message-----
> >> From: Cédric Le Goater <clg@kaod.org>
> >> Sent: Monday, March 4, 2024 11:54 PM
> >> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> >> <peter.maydell@linaro.org>; Andrew Jeffery
> >> <andrew@codeconstruct.com.au>; Joel Stanley <joel@jms.id.au>;
> >> Alistair Francis <alistair@alistair23.me>; open list:ASPEED BMCs
> >> <qemu-arm@nongnu.org>; open list:All patches CC here
> >> <qemu-devel@nongnu.org>
> >> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> >> <yunlin.tang@aspeedtech.com>
> >> Subject: Re: [PATCH v2 0/9] Add AST2700 support
> >>
> >> Hello Jamin,
> >>
> >> On 3/4/24 10:29, Jamin Lin wrote:
> >>> Changes from v1:
> >>> The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for
> >>> AST2700
> >> SoC.
> >>>
> >>> Changes from v2:
> >>> - replace is_aarch64 with is_bus64bit for sdmc patch review.
> >>> - fix incorrect dram size for AST2700
> >>>
> >>> Test steps:
> >>> 1. Download openbmc image for AST2700 from
> >>> https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.00
> >>>
> >> https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.00/
> >>> ast2700-default-obmc.tar.gz
> >>> 2. untar ast2700-default-obmc.tar.gz
> >>> ```
> >>> tar -xf ast2700-default-obmc.tar.gz
> >>> ```
> >>> 3. Run and the contents of scripts as following
> >>> IMGDIR=ast2700-default UBOOT_SIZE=$(stat --format=%s -L
> >>> ${IMGDIR}/u-boot-nodtb.bin)
> >>> UBOOT_DTB_ADDR=$((0x400000000 + ${UBOOT_SIZE}))
> >>>
> >>> qemu-system-aarch64 -M ast2700-evb -nographic\
> >>> -device
> >> loader,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\
> >>> -device
> >>
> loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\
> >>> -device
> loader,addr=0x430000000,file=${IMGDIR}/bl31.bin,force-raw=on\
> >>> -device
> >> loader,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on
> >> \
> >>> -device loader,addr=0x430000000,cpu-num=0\
> >>> -device loader,addr=0x430000000,cpu-num=1\
> >>> -device loader,addr=0x430000000,cpu-num=2\
> >>> -device loader,addr=0x430000000,cpu-num=3\
> >>> -smp 4\
> >>> -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
> >>> -serial mon:stdio\
> >>> -snapshot
> >>>
> >>> Known Issue:
> >>> 1. QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
> >>> but not support Shared Peripheral Interrupt (SPI), yet.
> >>> Added work around in INTC patch to set GICINT132[18] which was BMC
> >>> UART interrupt if it received GICINT132, so users are able to type
> >>> any key from keyboard to trigger GICINT132 interrupt until AST2700
> >>> boot into login prompt. It is a temporary solution.
> >>> If users encounter boot stck and no booting log, please type any key
> >>> from keyboard.
> >>
> >> I haven't looked at the GIC issue but I started reviewing what I received.
> >>
> >> The mailer issue needs to be fixed before we consider this patches for
> merge.
> >> May be use an external email while keeping the same
> >> From: and Signed-off-by address.
> >>
> > Understand.
> > Thanks for your suggestion. I am asking our IT help to fix our smtp server
> issue.
> > They are fixing it. I will use my external account to send V3 patch
> > series if this issues does not be fixed, yet.
> >> When you resend, could you please add an avocado test ?
> >>
> > Sure, will create a patch for avocado test.
>
> Forgot to add,
>
> please update the documentation docs/system/arm/aspeed.rst.
>
Got it.
Thanks
> Thanks,
>
> C.
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
2024-03-04 14:47 ` Cédric Le Goater
@ 2024-03-11 7:21 ` Jamin Lin
2024-03-11 14:57 ` Cédric Le Goater
0 siblings, 1 reply; 24+ messages in thread
From: Jamin Lin @ 2024-03-11 7:21 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 10:47 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
>
Hi Cedrice,
Thanks for review and sorry reply you late.
> On 3/4/24 10:29, Jamin Lin wrote:
> > The SDRAM memory controller(DRAMC) controls the access to external
> > DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
> >
> > The DRAM memory controller of AST2700 is not backward compatible to
> > previous chips such AST2600, AST2500 and AST2400.
> >
> > Max memory is now 8GiB on the AST2700. Introduce new
> aspeed_2700_sdmc
> > and class with read/write operation and reset handlers.
> >
> > Define DRAMC necessary protected registers and unprotected registers
> > for AST2700 and increase the register set to 0x1000.
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> > hw/misc/aspeed_sdmc.c | 215
> ++++++++++++++++++++++++++++++----
> > include/hw/misc/aspeed_sdmc.h | 4 +-
> > 2 files changed, 198 insertions(+), 21 deletions(-)
> >
> > diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index
> > 64cd1a81dc..63fb7936c4 100644
> > --- a/hw/misc/aspeed_sdmc.c
> > +++ b/hw/misc/aspeed_sdmc.c
> > @@ -27,6 +27,7 @@
> > #define PROT_SOFTLOCKED 0x00
> >
> > #define PROT_KEY_UNLOCK 0xFC600309
> > +#define PROT_2700_KEY_UNLOCK 0x1688A8A8
> > #define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
> >
> > /* Configuration Register */
> > @@ -54,6 +55,46 @@
> > #define R_DRAM_TIME (0x8c / 4)
> > #define R_ECC_ERR_INJECT (0xb4 / 4)
> >
> > +/* AST2700 Register */
> > +#define R_2700_PROT (0x00 / 4)
> > +#define R_INT_STATUS (0x04 / 4)
> > +#define R_INT_CLEAR (0x08 / 4)
> > +#define R_INT_MASK (0x0c / 4)
> > +#define R_MAIN_CONF (0x10 / 4)
> > +#define R_MAIN_CONTROL (0x14 / 4)
> > +#define R_MAIN_STATUS (0x18 / 4)
> > +#define R_ERR_STATUS (0x1c / 4)
> > +#define R_ECC_FAIL_STATUS (0x78 / 4)
> > +#define R_ECC_FAIL_ADDR (0x7c / 4)
> > +#define R_ECC_TESTING_CONTROL (0x80 / 4)
> > +#define R_PROT_REGION_LOCK_STATUS (0x94 / 4)
> > +#define R_TEST_FAIL_ADDR (0xd4 / 4)
> > +#define R_TEST_FAIL_D0 (0xd8 / 4)
> > +#define R_TEST_FAIL_D1 (0xdc / 4)
> > +#define R_TEST_FAIL_D2 (0xe0 / 4)
> > +#define R_TEST_FAIL_D3 (0xe4 / 4)
> > +#define R_DBG_STATUS (0xf4 / 4)
> > +#define R_PHY_INTERFACE_STATUS (0xf8 / 4)
> > +#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4)
> > +#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4) #define
> > +R_PORT0_INTERFACE_MONITOR1 (0x244 / 4) #define
> > +R_PORT0_INTERFACE_MONITOR2 (0x248 / 4) #define
> > +R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4) #define
> > +R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4) #define
> > +R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4) #define
> > +R_PORT2_INTERFACE_MONITOR0 (0x340 / 4) #define
> > +R_PORT2_INTERFACE_MONITOR1 (0x344 / 4) #define
> > +R_PORT2_INTERFACE_MONITOR2 (0x348 / 4) #define
> > +R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4) #define
> > +R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4) #define
> > +R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4) #define
> > +R_PORT4_INTERFACE_MONITOR0 (0x440 / 4) #define
> > +R_PORT4_INTERFACE_MONITOR1 (0x444 / 4) #define
> > +R_PORT4_INTERFACE_MONITOR2 (0x448 / 4) #define
> > +R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4) #define
> > +R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4) #define
> > +R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4)
> > +
> > /*
> > * Configuration register Ox4 (for Aspeed AST2400 SOC)
> > *
> > @@ -76,10 +117,6 @@
> > #define ASPEED_SDMC_VGA_32MB 0x2
> > #define ASPEED_SDMC_VGA_64MB 0x3
> > #define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
> > -#define ASPEED_SDMC_DRAM_64MB 0x0
> > -#define ASPEED_SDMC_DRAM_128MB 0x1
> > -#define ASPEED_SDMC_DRAM_256MB 0x2
> > -#define ASPEED_SDMC_DRAM_512MB 0x3
> >
> > #define ASPEED_SDMC_READONLY_MASK \
> > (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
> > @@ -100,22 +137,24 @@
> > #define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs
> from AST2400 */
> > #define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs
> from AST2400 */
> >
> > -/* DRAM size definitions differs */
> > -#define ASPEED_SDMC_AST2500_128MB 0x0
> > -#define ASPEED_SDMC_AST2500_256MB 0x1
> > -#define ASPEED_SDMC_AST2500_512MB 0x2
> > -#define ASPEED_SDMC_AST2500_1024MB 0x3
> > -
> > -#define ASPEED_SDMC_AST2600_256MB 0x0
> > -#define ASPEED_SDMC_AST2600_512MB 0x1
> > -#define ASPEED_SDMC_AST2600_1024MB 0x2
> > -#define ASPEED_SDMC_AST2600_2048MB 0x3
> > -
> Please move the removal above in a separate patch.
Will fix
>
> > #define ASPEED_SDMC_AST2500_READONLY_MASK
> \
> > (ASPEED_SDMC_HW_VERSION(0xf) |
> ASPEED_SDMC_CACHE_INITIAL_DONE | \
> > ASPEED_SDMC_AST2500_RESERVED |
> ASPEED_SDMC_VGA_COMPAT | \
> > ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
> >
> > +/*
> > + * Main Configuration register Ox10 (for Aspeed AST2700 SOC and
> > +higher)
> > + *
> > + */
> > +#define ASPEED_SDMC_AST2700_RESERVED 0xFFFF2082 /* 31:16,
> 13, 7, 1 */
> > +#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8)
> > +#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6)
> > +#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE (1 << 5)
> > +#define ASPEED_SDMC_AST2700_DRAM_SIZE(x) ((x & 0x7)
> << 2)
> > +
> > +#define ASPEED_SDMC_AST2700_READONLY_MASK \
> > + (ASPEED_SDMC_AST2700_RESERVED)
> > +
> > static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned
> size)
> > {
> > AspeedSDMCState *s = ASPEED_SDMC(opaque); @@ -231,7 +270,10
> @@
> > static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
> > AspeedSDMCState *s = ASPEED_SDMC(dev);
> > AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> >
> > - assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> > + if (!asc->is_bus64bit) {
> > + assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> > + }
>
> May be :
>
> assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
>
> ?
Will fix
>
> > +
> > s->max_ram_size = asc->max_ram_size;
> >
> > memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops,
> s,
> > @@ -311,7 +353,8 @@ static void
> aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> > uint32_t data)
> > {
> > if (reg == R_PROT) {
> > - s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> PROT_SOFTLOCKED;
> > + s->regs[reg] =
> > + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> > + PROT_SOFTLOCKED;
> > return;
> > }
> >
> > @@ -369,7 +412,8 @@ static void
> aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> > uint32_t data)
> > {
> > if (reg == R_PROT) {
> > - s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> PROT_SOFTLOCKED;
> > + s->regs[reg] =
> > + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> > + PROT_SOFTLOCKED;
> > return;
> > }
> >
> > @@ -449,8 +493,9 @@ static void
> aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> > }
> >
> > if (s->regs[R_PROT] == PROT_HARDLOCKED) {
> > - qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until
> system reset!\n",
> > - __func__);
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: SDMC is locked until system reset!\n",
> > + __func__);
> > return;
> > }
>
> The checkpatch changes could be in a separate patch. This is minor.
Will fix
>
> >
> > @@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info = {
> > .class_init = aspeed_2600_sdmc_class_init,
> > };
> >
> > +static void aspeed_2700_sdmc_reset(DeviceState *dev) {
> > + AspeedSDMCState *s = ASPEED_SDMC(dev);
> > + AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> > +
> > + memset(s->regs, 0, sizeof(s->regs));
> > +
> > + /* Set ram size bit and defaults values */
> > + s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
> > + s->regs[R_2700_PROT] = PROT_UNLOCKED;
>
> The default reset value is unlocked ?
>
The sdmc controller is unlocked at the SPL stage for AST2700.
However, currently QEMU only support to emulate that AST2700 booting start at the u-boot stage.
That was why I set the default value was unlocked, so firmware(u-boot)
able to write the sdmc registers.
https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/board/aspeed/ibex_ast2700/sdram_ast2700.c#L716
https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/board/aspeed/ibex_ast2700/sdram_ast2700.c#L277
Thanks-Jamin
>
> Thanks,
>
> C.
>
>
>
> > +}
> > +
> > +static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s,
> > +uint32_t data) {
> > + uint32_t fixed_conf =
> ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
> > +
> ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
> > +
> > + /* Make sure readonly bits are kept */
> > + data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
> > +
> > + return data | fixed_conf;
> > +}
> > +
> > +static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> > + uint32_t data) {
> > + /* Unprotected registers */
> > + switch (reg) {
> > + case R_INT_STATUS:
> > + case R_INT_CLEAR:
> > + case R_INT_MASK:
> > + case R_MAIN_STATUS:
> > + case R_ERR_STATUS:
> > + case R_ECC_FAIL_STATUS:
> > + case R_ECC_FAIL_ADDR:
> > + case R_PROT_REGION_LOCK_STATUS:
> > + case R_TEST_FAIL_ADDR:
> > + case R_TEST_FAIL_D0:
> > + case R_TEST_FAIL_D1:
> > + case R_TEST_FAIL_D2:
> > + case R_TEST_FAIL_D3:
> > + case R_DBG_STATUS:
> > + case R_PHY_INTERFACE_STATUS:
> > + case R_GRAPHIC_MEM_BASE_ADDR:
> > + case R_PORT0_INTERFACE_MONITOR0:
> > + case R_PORT0_INTERFACE_MONITOR1:
> > + case R_PORT0_INTERFACE_MONITOR2:
> > + case R_PORT1_INTERFACE_MONITOR0:
> > + case R_PORT1_INTERFACE_MONITOR1:
> > + case R_PORT1_INTERFACE_MONITOR2:
> > + case R_PORT2_INTERFACE_MONITOR0:
> > + case R_PORT2_INTERFACE_MONITOR1:
> > + case R_PORT2_INTERFACE_MONITOR2:
> > + case R_PORT3_INTERFACE_MONITOR0:
> > + case R_PORT3_INTERFACE_MONITOR1:
> > + case R_PORT3_INTERFACE_MONITOR2:
> > + case R_PORT4_INTERFACE_MONITOR0:
> > + case R_PORT4_INTERFACE_MONITOR1:
> > + case R_PORT4_INTERFACE_MONITOR2:
> > + case R_PORT5_INTERFACE_MONITOR0:
> > + case R_PORT5_INTERFACE_MONITOR1:
> > + case R_PORT5_INTERFACE_MONITOR2:
> > + s->regs[reg] = data;
> > + return;
> > + }
> > +
> > + if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: SDMC is locked until system reset!\n",
> > + __func__);
> > + return;
> > + }
> > +
> > + if (reg != R_2700_PROT && s->regs[R_2700_PROT] ==
> PROT_SOFTLOCKED) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: SDMC is locked! (write to MCR%02x
> blocked)\n",
> > + __func__, reg * 4);
> > + return;
> > + }
> > +
> > + switch (reg) {
> > + case R_2700_PROT:
> > + if (data == PROT_2700_KEY_UNLOCK) {
> > + data = PROT_UNLOCKED;
> > + } else if (data == PROT_KEY_HARDLOCK) {
> > + data = PROT_HARDLOCKED;
> > + } else {
> > + data = PROT_SOFTLOCKED;
> > + }
> > + break;
> > + case R_MAIN_CONF:
> > + data = aspeed_2700_sdmc_compute_conf(s, data);
> > + break;
> > + case R_MAIN_STATUS:
> > + /* Will never return 'busy'. */
> > + data &= ~PHY_BUSY_STATE;
> > + break;
> > + default:
> > + break;
> > + }
> > +
> > + s->regs[reg] = data;
> > +}
> > +
> > +static const uint64_t
> > + aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
> > + 2048 * MiB, 4096 * MiB, 8192 *
> MiB,
> > +0};
> > +
> > +static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
> > +
> > + dc->desc = "ASPEED 2700 SDRAM Memory Controller";
> > + dc->reset = aspeed_2700_sdmc_reset;
> > +
> > + asc->is_bus64bit = true;
> > + asc->max_ram_size = 8 * GiB;
> > + asc->compute_conf = aspeed_2700_sdmc_compute_conf;
> > + asc->write = aspeed_2700_sdmc_write;
> > + asc->valid_ram_sizes = aspeed_2700_ram_sizes; }
> > +
> > +static const TypeInfo aspeed_2700_sdmc_info = {
> > + .name = TYPE_ASPEED_2700_SDMC,
> > + .parent = TYPE_ASPEED_SDMC,
> > + .class_init = aspeed_2700_sdmc_class_init, };
> > +
> > static void aspeed_sdmc_register_types(void)
> > {
> > type_register_static(&aspeed_sdmc_info);
> > type_register_static(&aspeed_2400_sdmc_info);
> > type_register_static(&aspeed_2500_sdmc_info);
> > type_register_static(&aspeed_2600_sdmc_info);
> > + type_register_static(&aspeed_2700_sdmc_info);
> > }
> >
> > type_init(aspeed_sdmc_register_types);
> > diff --git a/include/hw/misc/aspeed_sdmc.h
> > b/include/hw/misc/aspeed_sdmc.h index ec2d59a14f..6df2f0a3b7 100644
> > --- a/include/hw/misc/aspeed_sdmc.h
> > +++ b/include/hw/misc/aspeed_sdmc.h
> > @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
> AspeedSDMCClass, ASPEED_SDMC)
> > #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
> > #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
> > #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
> > +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
> >
> > /*
> > * SDMC has 174 documented registers. In addition the u-boot device
> > tree @@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
> AspeedSDMCClass, ASPEED_SDMC)
> > * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
> > * training.
> > */
> > -#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
> > +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
> >
> > struct AspeedSDMCState {
> > /*< private >*/
> > @@ -51,6 +52,7 @@ struct AspeedSDMCClass {
> > const uint64_t *valid_ram_sizes;
> > uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
> > void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
> > + bool is_bus64bit;
> > };
> >
> > #endif /* ASPEED_SDMC_H */
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 7/9] aspeed/soc: Add AST2700 support
2024-03-04 15:49 ` [PATCH v2 7/9] aspeed/soc: Add AST2700 support Cédric Le Goater
@ 2024-03-11 10:31 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-11 10:31 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 11:50 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
> <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@aspeedtech.com>
> Subject: Re: [PATCH v2 7/9] aspeed/soc: Add AST2700 support
>
> On 3/4/24 10:29, Jamin Lin wrote:
> > Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35
> CPU).
> >
> > AST2700 SOC and its interrupt controller are too complex to handle in
> > the common Aspeed SoC framework. We introduce a new ast2700 class with
> > instance_init and realize handlers.
> >
> > AST2700 is a 64 bits quad core cpus and support 8 watchdog.
> > Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8.
> > In addition, update AspeedSocState to support scuio, sli, sliio and intc.
> >
> > Update silicon_rev data type to 64bits from AspeedSoCClass
>
> Why ? It is still 32bits in the models.
>
Hi Cedric,
Thanks for review and sorry reply you late.
You are right. I do not need to change silicon_rev data type because it is still 32bits.
Will fix.
Jamin
> The rest looks good.
>
> Thanks,
>
> C.
>
>
> > and
> > add TYPE_ASPEED27X0_SOC machine type.
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> > hw/arm/aspeed_ast27x0.c | 462
> ++++++++++++++++++++++++++++++++++++
> > hw/arm/meson.build | 1 +
> > include/hw/arm/aspeed_soc.h | 26 +-
> > 3 files changed, 486 insertions(+), 3 deletions(-)
> > create mode 100644 hw/arm/aspeed_ast27x0.c
> >
> > diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c new
> > file mode 100644 index 0000000000..c120994e5c
> > --- /dev/null
> > +++ b/hw/arm/aspeed_ast27x0.c
> > @@ -0,0 +1,462 @@
> > +/*
> > + * ASPEED SoC 27x0 family
> > + *
> > + * Copyright (C) 2024 ASPEED Technology Inc.
> > + *
> > + * This code is licensed under the GPL version 2 or later. See
> > + * the COPYING file in the top-level directory.
> > + *
> > + * Implementation extracted from the AST2600 and adapted for AST27x0.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "hw/misc/unimp.h"
> > +#include "hw/arm/aspeed_soc.h"
> > +#include "qemu/module.h"
> > +#include "qemu/error-report.h"
> > +#include "hw/i2c/aspeed_i2c.h"
> > +#include "net/net.h"
> > +#include "sysemu/sysemu.h"
> > +#include "hw/intc/arm_gicv3.h"
> > +#include "qapi/qmp/qlist.h"
> > +
> > +static const hwaddr aspeed_soc_ast2700_memmap[] = {
> > + [ASPEED_DEV_SPI_BOOT] = 0x400000000,
> > + [ASPEED_DEV_SRAM] = 0x10000000,
> > + [ASPEED_DEV_SDMC] = 0x12C00000,
> > + [ASPEED_DEV_SCU] = 0x12C02000,
> > + [ASPEED_DEV_SCUIO] = 0x14C02000,
> > + [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,
> > + [ASPEED_DEV_UART8] = 0X14C33700,
> > + [ASPEED_DEV_UART9] = 0X14C33800,
> > + [ASPEED_DEV_UART10] = 0X14C33900,
> > + [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_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_VIC] = 0x12100000,
> > + [ASPEED_DEV_SLI] = 0x12C17000,
> > + [ASPEED_DEV_SLIIO] = 0x14C1E000,
> > + [ASPEED_GIC_DIST] = 0x12200000,
> > + [ASPEED_GIC_REDIST] = 0x12280000,
> > +};
> > +
> > +#define AST2700_MAX_IRQ 288
> > +
> > +/* 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,
> > + [ASPEED_DEV_SDMC] = 0,
> > + [ASPEED_DEV_SCU] = 12,
> > + [ASPEED_DEV_ADC] = 130,
> > + [ASPEED_DEV_XDMA] = 5,
> > + [ASPEED_DEV_EMMC] = 15,
> > + [ASPEED_DEV_GPIO] = 11,
> > + [ASPEED_DEV_GPIO_1_8V] = 130,
> > + [ASPEED_DEV_RTC] = 13,
> > + [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_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,
> > +};
> > +
> > +static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int
> > +dev) {
> > + Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
> > + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> > +
> > + return qdev_get_gpio_in(a->intc.gic, sc->irqmap[dev]); }
> > +
> > +static void aspeed_soc_ast2700_init(Object *obj) {
> > + Aspeed27x0SoCState *a = ASPEED27X0_SOC(obj);
> > + AspeedSoCState *s = ASPEED_SOC(obj);
> > + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> > + int i;
> > + char socname[8];
> > + char typename[64];
> > +
> > + if (sscanf(sc->name, "%7s", socname) != 1) {
> > + g_assert_not_reached();
> > + }
> > +
> > + for (i = 0; i < sc->num_cpus; i++) {
> > + object_initialize_child(obj, "cpu[*]", &a->cpu[i],
> > + aspeed_soc_cpu_type(sc));
> > + }
> > +
> > + object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCU);
> > + qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
> > + 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);
> > +
> > + snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
> > + object_initialize_child(obj, "fmc", &s->fmc, typename);
> > +
> > + for (i = 0; i < sc->spis_num; i++) {
> > + snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i,
> socname);
> > + object_initialize_child(obj, "spi[*]", &s->spi[i], typename);
> > + }
> > +
> > + snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
> > + object_initialize_child(obj, "sdmc", &s->sdmc, typename);
> > + object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
> > + "ram-size");
> > +
> > + for (i = 0; i < sc->wdts_num; i++) {
> > + snprintf(typename, sizeof(typename), "aspeed.wdt-%s",
> socname);
> > + object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename);
> > + }
> > +
> > + for (i = 0; i < sc->macs_num; i++) {
> > + object_initialize_child(obj, "ftgmac100[*]", &s->ftgmac100[i],
> > + TYPE_FTGMAC100);
> > +
> > + object_initialize_child(obj, "mii[*]", &s->mii[i],
> TYPE_ASPEED_MII);
> > + }
> > +
> > + for (i = 0; i < sc->uarts_num; i++) {
> > + object_initialize_child(obj, "uart[*]", &s->uart[i],
> TYPE_SERIAL_MM);
> > + }
> > +
> > + 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_INTC);
> > +}
> > +
> > +/*
> > + * ASPEED ast2700 has 0xf as cluster ID
> > + *
> > + *
> > +https://developer.arm.com/documentation/ddi0388/e/the-system-control-
> > +coprocessors/summary-of-system-control-coprocessor-registers/multipro
> > +cessor-affinity-register
> > + */
> > +static uint64_t aspeed_calc_affinity(int cpu) {
> > + return (0x0 << ARM_AFF1_SHIFT) | cpu; }
> > +
> > +static void aspeed_soc_ast2700_gic(DeviceState *dev, Error **errp) {
> > + Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
> > + AspeedSoCState *s = ASPEED_SOC(dev);
> > + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> > + SysBusDevice *gicbusdev;
> > + QList *redist_region_count;
> > + int i;
> > +
> > + a->intc.gic = qdev_new(gicv3_class_name());
> > + qdev_prop_set_uint32(a->intc.gic, "revision", 3);
> > + qdev_prop_set_uint32(a->intc.gic, "num-cpu", sc->num_cpus);
> > + qdev_prop_set_uint32(a->intc.gic, "num-irq", AST2700_MAX_IRQ);
> > +
> > + redist_region_count = qlist_new();
> > + qlist_append_int(redist_region_count, sc->num_cpus);
> > + qdev_prop_set_array(a->intc.gic, "redist-region-count",
> > + redist_region_count);
> > +
> > + gicbusdev = SYS_BUS_DEVICE(a->intc.gic);
> > + sysbus_realize_and_unref(gicbusdev, errp);
> > + sysbus_mmio_map(gicbusdev, 0, sc->memmap[ASPEED_GIC_DIST]);
> > + sysbus_mmio_map(gicbusdev, 1, sc->memmap[ASPEED_GIC_REDIST]);
> > +
> > + for (i = 0; i < sc->num_cpus; i++) {
> > + DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
> > + int NUM_IRQS = 256, ARCH_GIC_MAINT_IRQ = 9,
> VIRTUAL_PMU_IRQ = 7;
> > + int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
> > +
> > + const int timer_irq[] = {
> > + [GTIMER_PHYS] = 14,
> > + [GTIMER_VIRT] = 11,
> > + [GTIMER_HYP] = 10,
> > + [GTIMER_SEC] = 13,
> > + };
> > + int j;
> > +
> > + for (j = 0; j < ARRAY_SIZE(timer_irq); j++) {
> > + qdev_connect_gpio_out(cpudev, j,
> > + qdev_get_gpio_in(a->intc.gic, ppibase +
> timer_irq[j]));
> > + }
> > +
> > + qemu_irq irq = qdev_get_gpio_in(a->intc.gic,
> > + ppibase +
> ARCH_GIC_MAINT_IRQ);
> > + qdev_connect_gpio_out_named(cpudev,
> "gicv3-maintenance-interrupt",
> > + 0, irq);
> > + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
> > + qdev_get_gpio_in(a->intc.gic, ppibase +
> > + VIRTUAL_PMU_IRQ));
> > +
> > + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev,
> ARM_CPU_IRQ));
> > + sysbus_connect_irq(gicbusdev, i + sc->num_cpus,
> > + qdev_get_gpio_in(cpudev,
> ARM_CPU_FIQ));
> > + sysbus_connect_irq(gicbusdev, i + 2 * sc->num_cpus,
> > + 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));
> > + }
> > +}
> > +
> > +static void aspeed_soc_ast2700_realize(DeviceState *dev, Error
> > +**errp) {
> > + int i;
> > + Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
> > + AspeedSoCState *s = ASPEED_SOC(dev);
> > + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> > + g_autofree char *sram_name = NULL;
> > +
> > + /* Default boot region (SPI memory or ROMs) */
> > + memory_region_init(&s->spi_boot_container, OBJECT(s),
> > + "aspeed.spi_boot_container", 0x400000000);
> > + memory_region_add_subregion(s->memory,
> sc->memmap[ASPEED_DEV_SPI_BOOT],
> > + &s->spi_boot_container);
> > +
> > + /* CPU */
> > + for (i = 0; i < sc->num_cpus; i++) {
> > + object_property_set_int(OBJECT(&a->cpu[i]), "mp-affinity",
> > + aspeed_calc_affinity(i),
> > + &error_abort);
> > +
> > + object_property_set_int(OBJECT(&a->cpu[i]), "cntfrq",
> 1125000000,
> > + &error_abort);
> > + object_property_set_link(OBJECT(&a->cpu[i]), "memory",
> > + OBJECT(s->memory),
> &error_abort);
> > +
> > + if (!qdev_realize(DEVICE(&a->cpu[i]), NULL, errp)) {
> > + return;
> > + }
> > + }
> > +
> > + /* GIC */
> > + aspeed_soc_ast2700_gic(dev, errp);
> > +
> > + /* INTC */
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc), errp)) {
> > + return;
> > + }
> > +
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0,
> sc->memmap[ASPEED_DEV_VIC]);
> > + sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), 0,
> > + qdev_get_gpio_in(DEVICE(&a->cpu),
> ARM_CPU_IRQ));
> > + sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), 1,
> > + qdev_get_gpio_in(DEVICE(&a->cpu),
> > + ARM_CPU_FIQ));
> > +
> > + /* SRAM */
> > + sram_name = g_strdup_printf("aspeed.sram.%d",
> CPU(&a->cpu[0])->cpu_index);
> > + if (!memory_region_init_ram(&s->sram, OBJECT(s), sram_name,
> sc->sram_size,
> > + errp)) {
> > + return;
> > + }
> > + memory_region_add_subregion(s->memory,
> > + sc->memmap[ASPEED_DEV_SRAM],
> > + &s->sram);
> > +
> > + /* SCU */
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0,
> > + sc->memmap[ASPEED_DEV_SCU]);
> > +
> > + /* SCU1 */
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scuio), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scuio), 0,
> > + sc->memmap[ASPEED_DEV_SCUIO]);
> > +
> > + /* UART */
> > + if (!aspeed_soc_uart_realize(s, errp)) {
> > + return;
> > + }
> > +
> > + /* FMC, The number of CS is set at the board level */
> > + object_property_set_link(OBJECT(&s->fmc), "dram",
> OBJECT(s->dram_mr),
> > + &error_abort);
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 0,
> sc->memmap[ASPEED_DEV_FMC]);
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 1,
> > +
> ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
> > + sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
> > + aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
> > +
> > + /* Set up an alias on the FMC CE0 region (boot default) */
> > + MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
> > + memory_region_init_alias(&s->spi_boot, OBJECT(s),
> "aspeed.spi_boot",
> > + fmc0_mmio, 0,
> memory_region_size(fmc0_mmio));
> > + memory_region_add_subregion(&s->spi_boot_container, 0x0,
> > + &s->spi_boot);
> > +
> > + /* SPI */
> > + for (i = 0; i < sc->spis_num; i++) {
> > + object_property_set_link(OBJECT(&s->spi[i]), "dram",
> > + OBJECT(s->dram_mr),
> &error_abort);
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 0,
> > + sc->memmap[ASPEED_DEV_SPI0 + i]);
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 1,
> > +
> ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
> > + }
> > +
> > + /* SDMC - SDRAM Memory Controller */
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdmc), 0,
> > + sc->memmap[ASPEED_DEV_SDMC]);
> > +
> > + /* RAM */
> > + if (!aspeed_soc_dram_init(s, errp)) {
> > + return;
> > + }
> > +
> > + for (i = 0; i < sc->macs_num; i++) {
> > + object_property_set_bool(OBJECT(&s->ftgmac100[i]), "aspeed",
> true,
> > + &error_abort);
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
> > + sc->memmap[ASPEED_DEV_ETH1 + i]);
> > + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
> > + aspeed_soc_get_irq(s, ASPEED_DEV_ETH1
> +
> > + i));
> > +
> > + object_property_set_link(OBJECT(&s->mii[i]), "nic",
> > + OBJECT(&s->ftgmac100[i]),
> &error_abort);
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mii[i]), errp)) {
> > + return;
> > + }
> > +
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->mii[i]), 0,
> > + sc->memmap[ASPEED_DEV_MII1 + i]);
> > + }
> > +
> > + /* Watch dog */
> > + for (i = 0; i < sc->wdts_num; i++) {
> > + AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
> > + hwaddr wdt_offset = sc->memmap[ASPEED_DEV_WDT] + i *
> > + awc->iosize;
> > +
> > + object_property_set_link(OBJECT(&s->wdt[i]), "scu",
> OBJECT(&s->scu),
> > + &error_abort);
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->wdt[i]), 0,
> wdt_offset);
> > + }
> > +
> > + /* SLI */
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sli), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sli), 0,
> > + sc->memmap[ASPEED_DEV_SLI]);
> > +
> > + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sliio), errp)) {
> > + return;
> > + }
> > + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sliio), 0,
> > + sc->memmap[ASPEED_DEV_SLIIO]);
> > +
> > + create_unimplemented_device("ast2700.dpmcu", 0x11000000,
> 0x40000);
> > + create_unimplemented_device("ast2700.iomem0", 0x12000000,
> 0x01000000);
> > + create_unimplemented_device("ast2700.iomem1", 0x14000000,
> 0x01000000);
> > + create_unimplemented_device("ast2700.ltpi", 0x30000000,
> 0x1000000);
> > + create_unimplemented_device("ast2700.io", 0x0, 0x4000000); }
> > +
> > +static void aspeed_soc_ast2700_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);
> > +
> > + 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;
> > + sc->spis_num = 3;
> > + sc->wdts_num = 8;
> > + sc->macs_num = 1;
> > + sc->uarts_num = 13;
> > + sc->num_cpus = 4;
> > + sc->uarts_base = ASPEED_DEV_UART0;
> > + sc->irqmap = aspeed_soc_ast2700_irqmap;
> > + sc->memmap = aspeed_soc_ast2700_memmap;
> > + sc->get_irq = aspeed_soc_ast2700_get_irq;
> > +}
> > +
> > +static const TypeInfo aspeed_soc_ast27x0_types[] = {
> > + {
> > + .name = TYPE_ASPEED27X0_SOC,
> > + .parent = TYPE_ASPEED_SOC,
> > + .instance_size = sizeof(Aspeed27x0SoCState),
> > + .abstract = true,
> > + }, {
> > + .name = "ast2700-a0",
> > + .parent = TYPE_ASPEED27X0_SOC,
> > + .instance_init = aspeed_soc_ast2700_init,
> > + .class_init = aspeed_soc_ast2700_class_init,
> > + },
> > +};
> > +
> > +DEFINE_TYPES(aspeed_soc_ast27x0_types)
> > diff --git a/hw/arm/meson.build b/hw/arm/meson.build index
> > 6808135c1f..1e3295a423 100644
> > --- a/hw/arm/meson.build
> > +++ b/hw/arm/meson.build
> > @@ -46,6 +46,7 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true:
> files(
> > 'aspeed_soc_common.c',
> > 'aspeed_ast2400.c',
> > 'aspeed_ast2600.c',
> > + 'aspeed_ast27x0.c',
> > 'aspeed_ast10x0.c',
> > 'aspeed_eeprom.c',
> > 'fby35.c'))
> > diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> > index c60fac900a..fab5abff9e 100644
> > --- a/include/hw/arm/aspeed_soc.h
> > +++ b/include/hw/arm/aspeed_soc.h
> > @@ -26,6 +26,7 @@
> > #include "hw/ssi/aspeed_smc.h"
> > #include "hw/misc/aspeed_hace.h"
> > #include "hw/misc/aspeed_sbc.h"
> > +#include "hw/misc/aspeed_sli.h"
> > #include "hw/watchdog/wdt_aspeed.h"
> > #include "hw/net/ftgmac100.h"
> > #include "target/arm/cpu.h"
> > @@ -41,8 +42,8 @@
> >
> > #define ASPEED_SPIS_NUM 2
> > #define ASPEED_EHCIS_NUM 2
> > -#define ASPEED_WDTS_NUM 4
> > -#define ASPEED_CPUS_NUM 2
> > +#define ASPEED_WDTS_NUM 8
> > +#define ASPEED_CPUS_NUM 4
> > #define ASPEED_MACS_NUM 4
> > #define ASPEED_UARTS_NUM 13
> > #define ASPEED_JTAG_NUM 2
> > @@ -61,6 +62,7 @@ struct AspeedSoCState {
> > AspeedI2CState i2c;
> > AspeedI3CState i3c;
> > AspeedSCUState scu;
> > + AspeedSCUState scuio;
> > AspeedHACEState hace;
> > AspeedXDMAState xdma;
> > AspeedADCState adc;
> > @@ -68,6 +70,8 @@ struct AspeedSoCState {
> > AspeedSMCState spi[ASPEED_SPIS_NUM];
> > EHCISysBusState ehci[ASPEED_EHCIS_NUM];
> > AspeedSBCState sbc;
> > + AspeedSLIState sli;
> > + AspeedSLIState sliio;
> > MemoryRegion secsram;
> > UnimplementedDeviceState sbc_unimplemented;
> > AspeedSDMCState sdmc;
> > @@ -117,6 +121,16 @@ struct Aspeed2600SoCState {
> > #define TYPE_ASPEED2600_SOC "aspeed2600-soc"
> > OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2600SoCState,
> ASPEED2600_SOC)
> >
> > +struct Aspeed27x0SoCState {
> > + AspeedSoCState parent;
> > +
> > + ARMCPU cpu[ASPEED_CPUS_NUM];
> > + AspeedINTCState intc;
> > +};
> > +
> > +#define TYPE_ASPEED27X0_SOC "aspeed27x0-soc"
> > +OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0SoCState, ASPEED27X0_SOC)
> > +
> > struct Aspeed10x0SoCState {
> > AspeedSoCState parent;
> >
> > @@ -132,7 +146,7 @@ struct AspeedSoCClass {
> > const char *name;
> > /** valid_cpu_types: NULL terminated array of a single CPU type. */
> > const char * const *valid_cpu_types;
> > - uint32_t silicon_rev;
> > + uint64_t silicon_rev;
> > uint64_t sram_size;
> > uint64_t secsram_size;
> > int spis_num;
> > @@ -168,6 +182,7 @@ enum {
> > ASPEED_DEV_UART13,
> > ASPEED_DEV_VUART,
> > ASPEED_DEV_FMC,
> > + ASPEED_DEV_SPI0,
> > ASPEED_DEV_SPI1,
> > ASPEED_DEV_SPI2,
> > ASPEED_DEV_EHCI1,
> > @@ -222,6 +237,11 @@ enum {
> > ASPEED_DEV_JTAG1,
> > ASPEED_DEV_FSI1,
> > ASPEED_DEV_FSI2,
> > + ASPEED_DEV_SCUIO,
> > + ASPEED_DEV_SLI,
> > + ASPEED_DEV_SLIIO,
> > + ASPEED_GIC_DIST,
> > + ASPEED_GIC_REDIST,
> > };
> >
> > qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
2024-03-11 7:21 ` Jamin Lin
@ 2024-03-11 14:57 ` Cédric Le Goater
2024-03-12 3:42 ` Jamin Lin
0 siblings, 1 reply; 24+ messages in thread
From: Cédric Le Goater @ 2024-03-11 14:57 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Andrew Jeffery, Joel Stanley,
Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
On 3/11/24 08:21, Jamin Lin wrote:
>> -----Original Message-----
>> From: Cédric Le Goater <clg@kaod.org>
>> Sent: Monday, March 4, 2024 10:47 PM
>> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
>> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
>> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; open
>> list:ASPEED BMCs <qemu-arm@nongnu.org>; open list:All patches CC here
>> <qemu-devel@nongnu.org>
>> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
>> <yunlin.tang@aspeedtech.com>
>> Subject: Re: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
>>
> Hi Cedrice,
>
> Thanks for review and sorry reply you late.
>
>> On 3/4/24 10:29, Jamin Lin wrote:
>>> The SDRAM memory controller(DRAMC) controls the access to external
>>> DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
>>>
>>> The DRAM memory controller of AST2700 is not backward compatible to
>>> previous chips such AST2600, AST2500 and AST2400.
>>>
>>> Max memory is now 8GiB on the AST2700. Introduce new
>> aspeed_2700_sdmc
>>> and class with read/write operation and reset handlers.
>>>
>>> Define DRAMC necessary protected registers and unprotected registers
>>> for AST2700 and increase the register set to 0x1000.
>>>
>>> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
>>> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
>>> ---
>>> hw/misc/aspeed_sdmc.c | 215
>> ++++++++++++++++++++++++++++++----
>>> include/hw/misc/aspeed_sdmc.h | 4 +-
>>> 2 files changed, 198 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index
>>> 64cd1a81dc..63fb7936c4 100644
>>> --- a/hw/misc/aspeed_sdmc.c
>>> +++ b/hw/misc/aspeed_sdmc.c
>>> @@ -27,6 +27,7 @@
>>> #define PROT_SOFTLOCKED 0x00
>>>
>>> #define PROT_KEY_UNLOCK 0xFC600309
>>> +#define PROT_2700_KEY_UNLOCK 0x1688A8A8
>>> #define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
>>>
>>> /* Configuration Register */
>>> @@ -54,6 +55,46 @@
>>> #define R_DRAM_TIME (0x8c / 4)
>>> #define R_ECC_ERR_INJECT (0xb4 / 4)
>>>
>>> +/* AST2700 Register */
>>> +#define R_2700_PROT (0x00 / 4)
>>> +#define R_INT_STATUS (0x04 / 4)
>>> +#define R_INT_CLEAR (0x08 / 4)
>>> +#define R_INT_MASK (0x0c / 4)
>>> +#define R_MAIN_CONF (0x10 / 4)
>>> +#define R_MAIN_CONTROL (0x14 / 4)
>>> +#define R_MAIN_STATUS (0x18 / 4)
>>> +#define R_ERR_STATUS (0x1c / 4)
>>> +#define R_ECC_FAIL_STATUS (0x78 / 4)
>>> +#define R_ECC_FAIL_ADDR (0x7c / 4)
>>> +#define R_ECC_TESTING_CONTROL (0x80 / 4)
>>> +#define R_PROT_REGION_LOCK_STATUS (0x94 / 4)
>>> +#define R_TEST_FAIL_ADDR (0xd4 / 4)
>>> +#define R_TEST_FAIL_D0 (0xd8 / 4)
>>> +#define R_TEST_FAIL_D1 (0xdc / 4)
>>> +#define R_TEST_FAIL_D2 (0xe0 / 4)
>>> +#define R_TEST_FAIL_D3 (0xe4 / 4)
>>> +#define R_DBG_STATUS (0xf4 / 4)
>>> +#define R_PHY_INTERFACE_STATUS (0xf8 / 4)
>>> +#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4)
>>> +#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4) #define
>>> +R_PORT0_INTERFACE_MONITOR1 (0x244 / 4) #define
>>> +R_PORT0_INTERFACE_MONITOR2 (0x248 / 4) #define
>>> +R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4) #define
>>> +R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4) #define
>>> +R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4) #define
>>> +R_PORT2_INTERFACE_MONITOR0 (0x340 / 4) #define
>>> +R_PORT2_INTERFACE_MONITOR1 (0x344 / 4) #define
>>> +R_PORT2_INTERFACE_MONITOR2 (0x348 / 4) #define
>>> +R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4) #define
>>> +R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4) #define
>>> +R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4) #define
>>> +R_PORT4_INTERFACE_MONITOR0 (0x440 / 4) #define
>>> +R_PORT4_INTERFACE_MONITOR1 (0x444 / 4) #define
>>> +R_PORT4_INTERFACE_MONITOR2 (0x448 / 4) #define
>>> +R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4) #define
>>> +R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4) #define
>>> +R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4)
>>> +
>>> /*
>>> * Configuration register Ox4 (for Aspeed AST2400 SOC)
>>> *
>>> @@ -76,10 +117,6 @@
>>> #define ASPEED_SDMC_VGA_32MB 0x2
>>> #define ASPEED_SDMC_VGA_64MB 0x3
>>> #define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
>>> -#define ASPEED_SDMC_DRAM_64MB 0x0
>>> -#define ASPEED_SDMC_DRAM_128MB 0x1
>>> -#define ASPEED_SDMC_DRAM_256MB 0x2
>>> -#define ASPEED_SDMC_DRAM_512MB 0x3
>>>
>>> #define ASPEED_SDMC_READONLY_MASK \
>>> (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
>>> @@ -100,22 +137,24 @@
>>> #define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs
>> from AST2400 */
>>> #define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs
>> from AST2400 */
>>>
>>> -/* DRAM size definitions differs */
>>> -#define ASPEED_SDMC_AST2500_128MB 0x0
>>> -#define ASPEED_SDMC_AST2500_256MB 0x1
>>> -#define ASPEED_SDMC_AST2500_512MB 0x2
>>> -#define ASPEED_SDMC_AST2500_1024MB 0x3
>>> -
>>> -#define ASPEED_SDMC_AST2600_256MB 0x0
>>> -#define ASPEED_SDMC_AST2600_512MB 0x1
>>> -#define ASPEED_SDMC_AST2600_1024MB 0x2
>>> -#define ASPEED_SDMC_AST2600_2048MB 0x3
>>> -
>> Please move the removal above in a separate patch.
> Will fix
>>
>>> #define ASPEED_SDMC_AST2500_READONLY_MASK
>> \
>>> (ASPEED_SDMC_HW_VERSION(0xf) |
>> ASPEED_SDMC_CACHE_INITIAL_DONE | \
>>> ASPEED_SDMC_AST2500_RESERVED |
>> ASPEED_SDMC_VGA_COMPAT | \
>>> ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
>>>
>>> +/*
>>> + * Main Configuration register Ox10 (for Aspeed AST2700 SOC and
>>> +higher)
>>> + *
>>> + */
>>> +#define ASPEED_SDMC_AST2700_RESERVED 0xFFFF2082 /* 31:16,
>> 13, 7, 1 */
>>> +#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8)
>>> +#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6)
>>> +#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE (1 << 5)
>>> +#define ASPEED_SDMC_AST2700_DRAM_SIZE(x) ((x & 0x7)
>> << 2)
>>> +
>>> +#define ASPEED_SDMC_AST2700_READONLY_MASK \
>>> + (ASPEED_SDMC_AST2700_RESERVED)
>>> +
>>> static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned
>> size)
>>> {
>>> AspeedSDMCState *s = ASPEED_SDMC(opaque); @@ -231,7 +270,10
>> @@
>>> static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
>>> AspeedSDMCState *s = ASPEED_SDMC(dev);
>>> AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
>>>
>>> - assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
>>> + if (!asc->is_bus64bit) {
>>> + assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
>>> + }
>>
>> May be :
>>
>> assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
>>
>> ?
> Will fix
>>
>>> +
>>> s->max_ram_size = asc->max_ram_size;
>>>
>>> memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops,
>> s,
>>> @@ -311,7 +353,8 @@ static void
>> aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
>>> uint32_t data)
>>> {
>>> if (reg == R_PROT) {
>>> - s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
>> PROT_SOFTLOCKED;
>>> + s->regs[reg] =
>>> + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
>>> + PROT_SOFTLOCKED;
>>> return;
>>> }
>>>
>>> @@ -369,7 +412,8 @@ static void
>> aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
>>> uint32_t data)
>>> {
>>> if (reg == R_PROT) {
>>> - s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
>> PROT_SOFTLOCKED;
>>> + s->regs[reg] =
>>> + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
>>> + PROT_SOFTLOCKED;
>>> return;
>>> }
>>>
>>> @@ -449,8 +493,9 @@ static void
>> aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
>>> }
>>>
>>> if (s->regs[R_PROT] == PROT_HARDLOCKED) {
>>> - qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until
>> system reset!\n",
>>> - __func__);
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "%s: SDMC is locked until system reset!\n",
>>> + __func__);
>>> return;
>>> }
>>
>> The checkpatch changes could be in a separate patch. This is minor.
> Will fix
>>
>>>
>>> @@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info = {
>>> .class_init = aspeed_2600_sdmc_class_init,
>>> };
>>>
>>> +static void aspeed_2700_sdmc_reset(DeviceState *dev) {
>>> + AspeedSDMCState *s = ASPEED_SDMC(dev);
>>> + AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
>>> +
>>> + memset(s->regs, 0, sizeof(s->regs));
>>> +
>>> + /* Set ram size bit and defaults values */
>>> + s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
>>> + s->regs[R_2700_PROT] = PROT_UNLOCKED;
>>
>> The default reset value is unlocked ?
>>
> The sdmc controller is unlocked at the SPL stage for AST2700.
> However, currently QEMU only support to emulate that AST2700 booting start at the u-boot stage.
> That was why I set the default value was unlocked, so firmware(u-boot)
> able to write the sdmc registers.
> https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/board/aspeed/ibex_ast2700/sdram_ast2700.c#L716
> https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/board/aspeed/ibex_ast2700/sdram_ast2700.c#L277
Since the model is diverging from HW, a comment explaining the reason
why would be useful.
As an extension preparing SPL support, you could add a new "unlocked"
property, set to "false" by default. The AST2700 SoC realize handler
would set it to "true" and the reset handler would test the value to
initialize the R_PROT register.
Thanks,
C.
>
> Thanks-Jamin
>
>>
>> Thanks,
>>
>> C.
>>
>>
>>
>>> +}
>>> +
>>> +static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s,
>>> +uint32_t data) {
>>> + uint32_t fixed_conf =
>> ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
>>> +
>> ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
>>> +
>>> + /* Make sure readonly bits are kept */
>>> + data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
>>> +
>>> + return data | fixed_conf;
>>> +}
>>> +
>>> +static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
>>> + uint32_t data) {
>>> + /* Unprotected registers */
>>> + switch (reg) {
>>> + case R_INT_STATUS:
>>> + case R_INT_CLEAR:
>>> + case R_INT_MASK:
>>> + case R_MAIN_STATUS:
>>> + case R_ERR_STATUS:
>>> + case R_ECC_FAIL_STATUS:
>>> + case R_ECC_FAIL_ADDR:
>>> + case R_PROT_REGION_LOCK_STATUS:
>>> + case R_TEST_FAIL_ADDR:
>>> + case R_TEST_FAIL_D0:
>>> + case R_TEST_FAIL_D1:
>>> + case R_TEST_FAIL_D2:
>>> + case R_TEST_FAIL_D3:
>>> + case R_DBG_STATUS:
>>> + case R_PHY_INTERFACE_STATUS:
>>> + case R_GRAPHIC_MEM_BASE_ADDR:
>>> + case R_PORT0_INTERFACE_MONITOR0:
>>> + case R_PORT0_INTERFACE_MONITOR1:
>>> + case R_PORT0_INTERFACE_MONITOR2:
>>> + case R_PORT1_INTERFACE_MONITOR0:
>>> + case R_PORT1_INTERFACE_MONITOR1:
>>> + case R_PORT1_INTERFACE_MONITOR2:
>>> + case R_PORT2_INTERFACE_MONITOR0:
>>> + case R_PORT2_INTERFACE_MONITOR1:
>>> + case R_PORT2_INTERFACE_MONITOR2:
>>> + case R_PORT3_INTERFACE_MONITOR0:
>>> + case R_PORT3_INTERFACE_MONITOR1:
>>> + case R_PORT3_INTERFACE_MONITOR2:
>>> + case R_PORT4_INTERFACE_MONITOR0:
>>> + case R_PORT4_INTERFACE_MONITOR1:
>>> + case R_PORT4_INTERFACE_MONITOR2:
>>> + case R_PORT5_INTERFACE_MONITOR0:
>>> + case R_PORT5_INTERFACE_MONITOR1:
>>> + case R_PORT5_INTERFACE_MONITOR2:
>>> + s->regs[reg] = data;
>>> + return;
>>> + }
>>> +
>>> + if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "%s: SDMC is locked until system reset!\n",
>>> + __func__);
>>> + return;
>>> + }
>>> +
>>> + if (reg != R_2700_PROT && s->regs[R_2700_PROT] ==
>> PROT_SOFTLOCKED) {
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "%s: SDMC is locked! (write to MCR%02x
>> blocked)\n",
>>> + __func__, reg * 4);
>>> + return;
>>> + }
>>> +
>>> + switch (reg) {
>>> + case R_2700_PROT:
>>> + if (data == PROT_2700_KEY_UNLOCK) {
>>> + data = PROT_UNLOCKED;
>>> + } else if (data == PROT_KEY_HARDLOCK) {
>>> + data = PROT_HARDLOCKED;
>>> + } else {
>>> + data = PROT_SOFTLOCKED;
>>> + }
>>> + break;
>>> + case R_MAIN_CONF:
>>> + data = aspeed_2700_sdmc_compute_conf(s, data);
>>> + break;
>>> + case R_MAIN_STATUS:
>>> + /* Will never return 'busy'. */
>>> + data &= ~PHY_BUSY_STATE;
>>> + break;
>>> + default:
>>> + break;
>>> + }
>>> +
>>> + s->regs[reg] = data;
>>> +}
>>> +
>>> +static const uint64_t
>>> + aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
>>> + 2048 * MiB, 4096 * MiB, 8192 *
>> MiB,
>>> +0};
>>> +
>>> +static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void
>>> +*data) {
>>> + DeviceClass *dc = DEVICE_CLASS(klass);
>>> + AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
>>> +
>>> + dc->desc = "ASPEED 2700 SDRAM Memory Controller";
>>> + dc->reset = aspeed_2700_sdmc_reset;
>>> +
>>> + asc->is_bus64bit = true;
>>> + asc->max_ram_size = 8 * GiB;
>>> + asc->compute_conf = aspeed_2700_sdmc_compute_conf;
>>> + asc->write = aspeed_2700_sdmc_write;
>>> + asc->valid_ram_sizes = aspeed_2700_ram_sizes; }
>>> +
>>> +static const TypeInfo aspeed_2700_sdmc_info = {
>>> + .name = TYPE_ASPEED_2700_SDMC,
>>> + .parent = TYPE_ASPEED_SDMC,
>>> + .class_init = aspeed_2700_sdmc_class_init, };
>>> +
>>> static void aspeed_sdmc_register_types(void)
>>> {
>>> type_register_static(&aspeed_sdmc_info);
>>> type_register_static(&aspeed_2400_sdmc_info);
>>> type_register_static(&aspeed_2500_sdmc_info);
>>> type_register_static(&aspeed_2600_sdmc_info);
>>> + type_register_static(&aspeed_2700_sdmc_info);
>>> }
>>>
>>> type_init(aspeed_sdmc_register_types);
>>> diff --git a/include/hw/misc/aspeed_sdmc.h
>>> b/include/hw/misc/aspeed_sdmc.h index ec2d59a14f..6df2f0a3b7 100644
>>> --- a/include/hw/misc/aspeed_sdmc.h
>>> +++ b/include/hw/misc/aspeed_sdmc.h
>>> @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
>> AspeedSDMCClass, ASPEED_SDMC)
>>> #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
>>> #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
>>> #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
>>> +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
>>>
>>> /*
>>> * SDMC has 174 documented registers. In addition the u-boot device
>>> tree @@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
>> AspeedSDMCClass, ASPEED_SDMC)
>>> * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
>>> * training.
>>> */
>>> -#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
>>> +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
>>>
>>> struct AspeedSDMCState {
>>> /*< private >*/
>>> @@ -51,6 +52,7 @@ struct AspeedSDMCClass {
>>> const uint64_t *valid_ram_sizes;
>>> uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
>>> void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
>>> + bool is_bus64bit;
>>> };
>>>
>>> #endif /* ASPEED_SDMC_H */
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
2024-03-11 14:57 ` Cédric Le Goater
@ 2024-03-12 3:42 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-12 3:42 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> >>
> > Hi Cedrice,
> >
> > Thanks for review and sorry reply you late.
> >
> >> On 3/4/24 10:29, Jamin Lin wrote:
> >>> The SDRAM memory controller(DRAMC) controls the access to external
> >>> DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
> >>>
> >>> The DRAM memory controller of AST2700 is not backward compatible to
> >>> previous chips such AST2600, AST2500 and AST2400.
> >>>
> >>> Max memory is now 8GiB on the AST2700. Introduce new
> >> aspeed_2700_sdmc
> >>> and class with read/write operation and reset handlers.
> >>>
> >>> Define DRAMC necessary protected registers and unprotected registers
> >>> for AST2700 and increase the register set to 0x1000.
> >>>
> >>> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> >>> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> >>> ---
> >>> hw/misc/aspeed_sdmc.c | 215
> >> ++++++++++++++++++++++++++++++----
> >>> include/hw/misc/aspeed_sdmc.h | 4 +-
> >>> 2 files changed, 198 insertions(+), 21 deletions(-)
> >>>
> >>> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index
> >>> 64cd1a81dc..63fb7936c4 100644
> >>> --- a/hw/misc/aspeed_sdmc.c
> >>> +++ b/hw/misc/aspeed_sdmc.c
> >>> @@ -27,6 +27,7 @@
> >>> #define PROT_SOFTLOCKED 0x00
> >>>
> >>> #define PROT_KEY_UNLOCK 0xFC600309
> >>> +#define PROT_2700_KEY_UNLOCK 0x1688A8A8
> >>> #define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
> >>>
> >>> /* Configuration Register */
> >>> @@ -54,6 +55,46 @@
> >>> #define R_DRAM_TIME (0x8c / 4)
> >>> #define R_ECC_ERR_INJECT (0xb4 / 4)
> >>>
> >>> +/* AST2700 Register */
> >>> +#define R_2700_PROT (0x00 / 4)
> >>> +#define R_INT_STATUS (0x04 / 4)
> >>> +#define R_INT_CLEAR (0x08 / 4)
> >>> +#define R_INT_MASK (0x0c / 4)
> >>> +#define R_MAIN_CONF (0x10 / 4)
> >>> +#define R_MAIN_CONTROL (0x14 / 4)
> >>> +#define R_MAIN_STATUS (0x18 / 4)
> >>> +#define R_ERR_STATUS (0x1c / 4)
> >>> +#define R_ECC_FAIL_STATUS (0x78 / 4)
> >>> +#define R_ECC_FAIL_ADDR (0x7c / 4)
> >>> +#define R_ECC_TESTING_CONTROL (0x80 / 4)
> >>> +#define R_PROT_REGION_LOCK_STATUS (0x94 / 4)
> >>> +#define R_TEST_FAIL_ADDR (0xd4 / 4)
> >>> +#define R_TEST_FAIL_D0 (0xd8 / 4)
> >>> +#define R_TEST_FAIL_D1 (0xdc / 4)
> >>> +#define R_TEST_FAIL_D2 (0xe0 / 4)
> >>> +#define R_TEST_FAIL_D3 (0xe4 / 4)
> >>> +#define R_DBG_STATUS (0xf4 / 4)
> >>> +#define R_PHY_INTERFACE_STATUS (0xf8 / 4)
> >>> +#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4)
> >>> +#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4) #define
> >>> +R_PORT0_INTERFACE_MONITOR1 (0x244 / 4) #define
> >>> +R_PORT0_INTERFACE_MONITOR2 (0x248 / 4) #define
> >>> +R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4) #define
> >>> +R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4) #define
> >>> +R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4) #define
> >>> +R_PORT2_INTERFACE_MONITOR0 (0x340 / 4) #define
> >>> +R_PORT2_INTERFACE_MONITOR1 (0x344 / 4) #define
> >>> +R_PORT2_INTERFACE_MONITOR2 (0x348 / 4) #define
> >>> +R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4) #define
> >>> +R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4) #define
> >>> +R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4) #define
> >>> +R_PORT4_INTERFACE_MONITOR0 (0x440 / 4) #define
> >>> +R_PORT4_INTERFACE_MONITOR1 (0x444 / 4) #define
> >>> +R_PORT4_INTERFACE_MONITOR2 (0x448 / 4) #define
> >>> +R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4) #define
> >>> +R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4) #define
> >>> +R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4)
> >>> +
> >>> /*
> >>> * Configuration register Ox4 (for Aspeed AST2400 SOC)
> >>> *
> >>> @@ -76,10 +117,6 @@
> >>> #define ASPEED_SDMC_VGA_32MB 0x2
> >>> #define ASPEED_SDMC_VGA_64MB 0x3
> >>> #define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
> >>> -#define ASPEED_SDMC_DRAM_64MB 0x0
> >>> -#define ASPEED_SDMC_DRAM_128MB 0x1
> >>> -#define ASPEED_SDMC_DRAM_256MB 0x2
> >>> -#define ASPEED_SDMC_DRAM_512MB 0x3
> >>>
> >>> #define ASPEED_SDMC_READONLY_MASK
> \
> >>> (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT |
> \
> >>> @@ -100,22 +137,24 @@
> >>> #define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs
> >> from AST2400 */
> >>> #define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs
> >> from AST2400 */
> >>>
> >>> -/* DRAM size definitions differs */
> >>> -#define ASPEED_SDMC_AST2500_128MB 0x0
> >>> -#define ASPEED_SDMC_AST2500_256MB 0x1
> >>> -#define ASPEED_SDMC_AST2500_512MB 0x2
> >>> -#define ASPEED_SDMC_AST2500_1024MB 0x3
> >>> -
> >>> -#define ASPEED_SDMC_AST2600_256MB 0x0
> >>> -#define ASPEED_SDMC_AST2600_512MB 0x1
> >>> -#define ASPEED_SDMC_AST2600_1024MB 0x2
> >>> -#define ASPEED_SDMC_AST2600_2048MB 0x3
> >>> -
> >> Please move the removal above in a separate patch.
> > Will fix
> >>
> >>> #define ASPEED_SDMC_AST2500_READONLY_MASK
> >> \
> >>> (ASPEED_SDMC_HW_VERSION(0xf) |
> >> ASPEED_SDMC_CACHE_INITIAL_DONE | \
> >>> ASPEED_SDMC_AST2500_RESERVED |
> >> ASPEED_SDMC_VGA_COMPAT | \
> >>> ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
> >>>
> >>> +/*
> >>> + * Main Configuration register Ox10 (for Aspeed AST2700 SOC and
> >>> +higher)
> >>> + *
> >>> + */
> >>> +#define ASPEED_SDMC_AST2700_RESERVED 0xFFFF2082 /*
> 31:16,
> >> 13, 7, 1 */
> >>> +#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8)
> >>> +#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6)
> >>> +#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE (1 <<
> 5)
> >>> +#define ASPEED_SDMC_AST2700_DRAM_SIZE(x) ((x & 0x7)
> >> << 2)
> >>> +
> >>> +#define ASPEED_SDMC_AST2700_READONLY_MASK \
> >>> + (ASPEED_SDMC_AST2700_RESERVED)
> >>> +
> >>> static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr,
> >>> unsigned
> >> size)
> >>> {
> >>> AspeedSDMCState *s = ASPEED_SDMC(opaque); @@ -231,7
> +270,10
> >> @@
> >>> static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
> >>> AspeedSDMCState *s = ASPEED_SDMC(dev);
> >>> AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> >>>
> >>> - assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> >>> + if (!asc->is_bus64bit) {
> >>> + assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> >>> + }
> >>
> >> May be :
> >>
> >> assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
> >>
> >> ?
> > Will fix
> >>
> >>> +
> >>> s->max_ram_size = asc->max_ram_size;
> >>>
> >>> memory_region_init_io(&s->iomem, OBJECT(s),
> &aspeed_sdmc_ops,
> >> s,
> >>> @@ -311,7 +353,8 @@ static void
> >> aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >>> uint32_t data)
> >>> {
> >>> if (reg == R_PROT) {
> >>> - s->regs[reg] = (data == PROT_KEY_UNLOCK) ?
> PROT_UNLOCKED :
> >> PROT_SOFTLOCKED;
> >>> + s->regs[reg] =
> >>> + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> >>> + PROT_SOFTLOCKED;
> >>> return;
> >>> }
> >>>
> >>> @@ -369,7 +412,8 @@ static void
> >> aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >>> uint32_t data)
> >>> {
> >>> if (reg == R_PROT) {
> >>> - s->regs[reg] = (data == PROT_KEY_UNLOCK) ?
> PROT_UNLOCKED :
> >> PROT_SOFTLOCKED;
> >>> + s->regs[reg] =
> >>> + (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> >>> + PROT_SOFTLOCKED;
> >>> return;
> >>> }
> >>>
> >>> @@ -449,8 +493,9 @@ static void
> >> aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >>> }
> >>>
> >>> if (s->regs[R_PROT] == PROT_HARDLOCKED) {
> >>> - qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until
> >> system reset!\n",
> >>> - __func__);
> >>> + qemu_log_mask(LOG_GUEST_ERROR,
> >>> + "%s: SDMC is locked until system reset!\n",
> >>> + __func__);
> >>> return;
> >>> }
> >>
> >> The checkpatch changes could be in a separate patch. This is minor.
> > Will fix
> >>
> >>>
> >>> @@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info
> = {
> >>> .class_init = aspeed_2600_sdmc_class_init,
> >>> };
> >>>
> >>> +static void aspeed_2700_sdmc_reset(DeviceState *dev) {
> >>> + AspeedSDMCState *s = ASPEED_SDMC(dev);
> >>> + AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> >>> +
> >>> + memset(s->regs, 0, sizeof(s->regs));
> >>> +
> >>> + /* Set ram size bit and defaults values */
> >>> + s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
> >>> + s->regs[R_2700_PROT] = PROT_UNLOCKED;
> >>
> >> The default reset value is unlocked ?
> >>
> > The sdmc controller is unlocked at the SPL stage for AST2700.
> > However, currently QEMU only support to emulate that AST2700 booting
> start at the u-boot stage.
> > That was why I set the default value was unlocked, so firmware(u-boot)
> > able to write the sdmc registers.
> >
> https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/b
> > oard/aspeed/ibex_ast2700/sdram_ast2700.c#L716
> >
> https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/b
> > oard/aspeed/ibex_ast2700/sdram_ast2700.c#L277
>
> Since the model is diverging from HW, a comment explaining the reason why
> would be useful.
>
> As an extension preparing SPL support, you could add a new "unlocked"
> property, set to "false" by default. The AST2700 SoC realize handler would set
> it to "true" and the reset handler would test the value to initialize the R_PROT
> register.
>
Hi Cedric,
Thanks for your suggestion. Will add
Jamin
> Thanks,
>
> C.
>
>
>
> >
> > Thanks-Jamin
> >
> >>
> >> Thanks,
> >>
> >> C.
> >>
> >>
> >>
> >>> +}
> >>> +
> >>> +static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s,
> >>> +uint32_t data) {
> >>> + uint32_t fixed_conf =
> >> ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
> >>> +
> >> ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
> >>> +
> >>> + /* Make sure readonly bits are kept */
> >>> + data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
> >>> +
> >>> + return data | fixed_conf;
> >>> +}
> >>> +
> >>> +static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >>> + uint32_t data) {
> >>> + /* Unprotected registers */
> >>> + switch (reg) {
> >>> + case R_INT_STATUS:
> >>> + case R_INT_CLEAR:
> >>> + case R_INT_MASK:
> >>> + case R_MAIN_STATUS:
> >>> + case R_ERR_STATUS:
> >>> + case R_ECC_FAIL_STATUS:
> >>> + case R_ECC_FAIL_ADDR:
> >>> + case R_PROT_REGION_LOCK_STATUS:
> >>> + case R_TEST_FAIL_ADDR:
> >>> + case R_TEST_FAIL_D0:
> >>> + case R_TEST_FAIL_D1:
> >>> + case R_TEST_FAIL_D2:
> >>> + case R_TEST_FAIL_D3:
> >>> + case R_DBG_STATUS:
> >>> + case R_PHY_INTERFACE_STATUS:
> >>> + case R_GRAPHIC_MEM_BASE_ADDR:
> >>> + case R_PORT0_INTERFACE_MONITOR0:
> >>> + case R_PORT0_INTERFACE_MONITOR1:
> >>> + case R_PORT0_INTERFACE_MONITOR2:
> >>> + case R_PORT1_INTERFACE_MONITOR0:
> >>> + case R_PORT1_INTERFACE_MONITOR1:
> >>> + case R_PORT1_INTERFACE_MONITOR2:
> >>> + case R_PORT2_INTERFACE_MONITOR0:
> >>> + case R_PORT2_INTERFACE_MONITOR1:
> >>> + case R_PORT2_INTERFACE_MONITOR2:
> >>> + case R_PORT3_INTERFACE_MONITOR0:
> >>> + case R_PORT3_INTERFACE_MONITOR1:
> >>> + case R_PORT3_INTERFACE_MONITOR2:
> >>> + case R_PORT4_INTERFACE_MONITOR0:
> >>> + case R_PORT4_INTERFACE_MONITOR1:
> >>> + case R_PORT4_INTERFACE_MONITOR2:
> >>> + case R_PORT5_INTERFACE_MONITOR0:
> >>> + case R_PORT5_INTERFACE_MONITOR1:
> >>> + case R_PORT5_INTERFACE_MONITOR2:
> >>> + s->regs[reg] = data;
> >>> + return;
> >>> + }
> >>> +
> >>> + if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
> >>> + qemu_log_mask(LOG_GUEST_ERROR,
> >>> + "%s: SDMC is locked until system reset!\n",
> >>> + __func__);
> >>> + return;
> >>> + }
> >>> +
> >>> + if (reg != R_2700_PROT && s->regs[R_2700_PROT] ==
> >> PROT_SOFTLOCKED) {
> >>> + qemu_log_mask(LOG_GUEST_ERROR,
> >>> + "%s: SDMC is locked! (write to MCR%02x
> >> blocked)\n",
> >>> + __func__, reg * 4);
> >>> + return;
> >>> + }
> >>> +
> >>> + switch (reg) {
> >>> + case R_2700_PROT:
> >>> + if (data == PROT_2700_KEY_UNLOCK) {
> >>> + data = PROT_UNLOCKED;
> >>> + } else if (data == PROT_KEY_HARDLOCK) {
> >>> + data = PROT_HARDLOCKED;
> >>> + } else {
> >>> + data = PROT_SOFTLOCKED;
> >>> + }
> >>> + break;
> >>> + case R_MAIN_CONF:
> >>> + data = aspeed_2700_sdmc_compute_conf(s, data);
> >>> + break;
> >>> + case R_MAIN_STATUS:
> >>> + /* Will never return 'busy'. */
> >>> + data &= ~PHY_BUSY_STATE;
> >>> + break;
> >>> + default:
> >>> + break;
> >>> + }
> >>> +
> >>> + s->regs[reg] = data;
> >>> +}
> >>> +
> >>> +static const uint64_t
> >>> + aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
> >>> + 2048 * MiB, 4096 * MiB, 8192 *
> >> MiB,
> >>> +0};
> >>> +
> >>> +static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void
> >>> +*data) {
> >>> + DeviceClass *dc = DEVICE_CLASS(klass);
> >>> + AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
> >>> +
> >>> + dc->desc = "ASPEED 2700 SDRAM Memory Controller";
> >>> + dc->reset = aspeed_2700_sdmc_reset;
> >>> +
> >>> + asc->is_bus64bit = true;
> >>> + asc->max_ram_size = 8 * GiB;
> >>> + asc->compute_conf = aspeed_2700_sdmc_compute_conf;
> >>> + asc->write = aspeed_2700_sdmc_write;
> >>> + asc->valid_ram_sizes = aspeed_2700_ram_sizes; }
> >>> +
> >>> +static const TypeInfo aspeed_2700_sdmc_info = {
> >>> + .name = TYPE_ASPEED_2700_SDMC,
> >>> + .parent = TYPE_ASPEED_SDMC,
> >>> + .class_init = aspeed_2700_sdmc_class_init, };
> >>> +
> >>> static void aspeed_sdmc_register_types(void)
> >>> {
> >>> type_register_static(&aspeed_sdmc_info);
> >>> type_register_static(&aspeed_2400_sdmc_info);
> >>> type_register_static(&aspeed_2500_sdmc_info);
> >>> type_register_static(&aspeed_2600_sdmc_info);
> >>> + type_register_static(&aspeed_2700_sdmc_info);
> >>> }
> >>>
> >>> type_init(aspeed_sdmc_register_types);
> >>> diff --git a/include/hw/misc/aspeed_sdmc.h
> >>> b/include/hw/misc/aspeed_sdmc.h index ec2d59a14f..6df2f0a3b7 100644
> >>> --- a/include/hw/misc/aspeed_sdmc.h
> >>> +++ b/include/hw/misc/aspeed_sdmc.h
> >>> @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
> >> AspeedSDMCClass, ASPEED_SDMC)
> >>> #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
> >>> #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
> >>> #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
> >>> +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
> >>>
> >>> /*
> >>> * SDMC has 174 documented registers. In addition the u-boot
> >>> device tree @@ -29,7 +30,7 @@
> OBJECT_DECLARE_TYPE(AspeedSDMCState,
> >> AspeedSDMCClass, ASPEED_SDMC)
> >>> * time, and the other is in the DDR-PHY IP which is used during
> DDR-PHY
> >>> * training.
> >>> */
> >>> -#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
> >>> +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
> >>>
> >>> struct AspeedSDMCState {
> >>> /*< private >*/
> >>> @@ -51,6 +52,7 @@ struct AspeedSDMCClass {
> >>> const uint64_t *valid_ram_sizes;
> >>> uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
> >>> void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t
> >>> data);
> >>> + bool is_bus64bit;
> >>> };
> >>>
> >>> #endif /* ASPEED_SDMC_H */
> >
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH v2 4/9] aspeed/smc: Add AST2700 support
2024-03-04 15:19 ` Cédric Le Goater
@ 2024-03-12 9:58 ` Jamin Lin
0 siblings, 0 replies; 24+ messages in thread
From: Jamin Lin @ 2024-03-12 9:58 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee, Yunlin Tang
> On 3/4/24 10:29, Jamin Lin wrote:
> > AST2700 fmc/spi controller's address decoding unit is 64KB and only
> > bits [31:16] are used for decoding. Introduce seg_to_reg and
> > reg_to_seg handlers for ast2700 fmc/spi controller.
> > In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler.
> >
> > AST2700 support the maximum dram size is 8GiB.
> > Update dma_rw function and trace-event to support 64 bits dram
> > address. DMA length is from 1 byte to 32MB for AST2700, AST2600 and
> > AST10x0 and DMA length is from 4 bytes to 32MB for AST2500.
> >
> > In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
> > data for AST2700, AST2600 and AST10x0 and 4 bytes data for AST2500.
> > To support all ASPEED SOCs, adds dma_start_length parameter to store
> > the start length and update DMA_LENGTH mask to "1FFFFFF" to fix dma
> > moving incorrect data length issue.
> >
> > Currently, dma_rw function only supports length 4 bytes aligned.
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> > hw/ssi/aspeed_smc.c | 326
> +++++++++++++++++++++++++++++++++---
> > hw/ssi/trace-events | 2 +-
> > include/hw/ssi/aspeed_smc.h | 1 +
> > 3 files changed, 309 insertions(+), 20 deletions(-)
> >
> > diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index
> > 3c93936fd1..73121edf2b 100644
> > --- a/hw/ssi/aspeed_smc.c
> > +++ b/hw/ssi/aspeed_smc.c
> > @@ -131,6 +131,9 @@
> > #define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary
> 1: alternate */
> > #define FMC_WDT2_CTRL_EN BIT(0)
> >
> > +/* DMA DRAM Side Address High Part (AST2700) */
> > +#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4)
> > +
> > /* DMA Control/Status Register */
> > #define R_DMA_CTRL (0x80 / 4)
> > #define DMA_CTRL_REQUEST (1 << 31)
> > @@ -177,13 +180,18 @@
> > * DMA flash addresses should be 4 bytes aligned and the valid address
> > * range is 0x20000000 - 0x2FFFFFFF.
> > *
> > - * DMA length is from 4 bytes to 32MB
> > + * DMA length is from 4 bytes to 32MB (AST2500)
> > * 0: 4 bytes
> > * 0x7FFFFF: 32M bytes
> > + *
> > + * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700)
> > + * 0: 1 byte
> > + * 0x1FFFFFF: 32M bytes
>
> OK. Then, we need to fix the model first before adding AST2700 support.
Will add
>
> > */
> > #define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask)
> > +#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf)
> > #define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask)
> > -#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
> > +#define DMA_LENGTH(val) ((val) & 0x01FFFFFF)
> >
> > /* Flash opcodes. */
> > #define SPI_OP_READ 0x03 /* Read data bytes (low
> frequency) */
> > @@ -202,6 +210,7 @@ static const AspeedSegments
> aspeed_2500_spi2_segments[];
> > #define ASPEED_SMC_FEATURE_DMA 0x1
> > #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
> > #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
> > +#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
> >
> > static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
> > {
> > @@ -213,6 +222,11 @@ static inline bool
> aspeed_smc_has_wdt_control(const AspeedSMCClass *asc)
> > return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
> > }
> >
> > +static inline bool aspeed_smc_has_dma_dram_addr_high(const
> > +AspeedSMCClass *asc) {
> > + return !!(asc->features &
> ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
> > +}
> > +
> > #define aspeed_smc_error(fmt, ...)
> \
> > qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ##
> > __VA_ARGS__)
> >
> > @@ -655,7 +669,7 @@ static const MemoryRegionOps
> aspeed_smc_flash_ops = {
> > .endianness = DEVICE_LITTLE_ENDIAN,
> > .valid = {
> > .min_access_size = 1,
> > - .max_access_size = 4,
> > + .max_access_size = 8,
> > },
> > };
> >
> > @@ -734,6 +748,9 @@ static uint64_t aspeed_smc_read(void *opaque,
> hwaddr addr, unsigned int size)
> > (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
> > (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR)
> ||
> > (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR)
> ||
> > + (aspeed_smc_has_dma(asc) &&
> > + aspeed_smc_has_dma_dram_addr_high(asc) &&
> > + addr == R_DMA_DRAM_ADDR_HIGH) ||
> > (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
> > (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM)
> ||
> > (addr >= R_SEG_ADDR0 &&
> > @@ -840,8 +857,11 @@ static bool
> aspeed_smc_inject_read_failure(AspeedSMCState *s)
> > */
> > static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> > {
> > + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> > MemTxResult result;
> > + uint32_t dma_len;
> > uint32_t data;
> > + uint32_t extra;
> >
> > if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
> > aspeed_smc_error("invalid direction for DMA checksum"); @@
> > -852,7 +872,14 @@ static void
> aspeed_smc_dma_checksum(AspeedSMCState *s)
> > aspeed_smc_dma_calibration(s);
> > }
> >
> > - while (s->regs[R_DMA_LEN]) {
> > + dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
> > + /* dma length 4 bytes aligned */
> > + extra = dma_len % 4;
> > + if (extra != 0) {
> > + dma_len += 4 - extra;
> > + }
> > +
> > + while (dma_len) {
> > data = address_space_ldl_le(&s->flash_as,
> s->regs[R_DMA_FLASH_ADDR],
> > MEMTXATTRS_UNSPECIFIED,
> &result);
> > if (result != MEMTX_OK) {
> > @@ -868,7 +895,8 @@ static void
> aspeed_smc_dma_checksum(AspeedSMCState *s)
> > */
> > s->regs[R_DMA_CHECKSUM] += data;
> > s->regs[R_DMA_FLASH_ADDR] += 4;
> > - s->regs[R_DMA_LEN] -= 4;
> > + dma_len -= 4;
> > + s->regs[R_DMA_LEN] = dma_len;
> > }
> >
> > if (s->inject_failure && aspeed_smc_inject_read_failure(s)) { @@
> > -879,21 +907,44 @@ static void
> aspeed_smc_dma_checksum(AspeedSMCState
> > *s)
> >
> > static void aspeed_smc_dma_rw(AspeedSMCState *s)
> > {
> > + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> > + uint64_t dram_addr_high;
> > + uint64_t dma_dram_addr;
> > + uint64_t dram_addr;
> > MemTxResult result;
> > + uint32_t dma_len;
> > uint32_t data;
> > + uint32_t extra;
> > +
> > + if (aspeed_smc_has_dma_dram_addr_high(asc)) {
> > + dram_addr_high = s->regs[R_DMA_DRAM_ADDR_HIGH];
> > + dram_addr_high <<= 32;
> > + dma_dram_addr = dram_addr_high |
> s->regs[R_DMA_DRAM_ADDR];
> > + dram_addr = dma_dram_addr - s->dram_mr->container->addr;
> > + } else {
> > + dma_dram_addr = s->regs[R_DMA_DRAM_ADDR];
> > + dram_addr = dma_dram_addr;
> > + }
> > +
> > + dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
> > + /* dma length 4 bytes aligned */
> > + extra = dma_len % 4;
> > + if (extra != 0) {
> > + dma_len += 4 - extra;
> > + }
>
>
> I find the calculation in aspeed_smc_dma_checksum() and
> aspeed_smc_dma_rw() confusing. Can you please add helper routines to
> compute DMA_DRAM_ADDR and DMA_LEN ? Please do that in a separate
> patch before adding AST2700 support.
>
Will add
Thanks for your review and suggestion.
Jamin
>
> Thanks,
>
> C.
>
>
>
> > trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] &
> DMA_CTRL_WRITE ?
> > "write" : "read",
> > s->regs[R_DMA_FLASH_ADDR],
> > - s->regs[R_DMA_DRAM_ADDR],
> > - s->regs[R_DMA_LEN]);
> > - while (s->regs[R_DMA_LEN]) {
> > + dram_addr,
> > + dma_len);
> > +
> > + while (dma_len) {
> > if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
> > - data = address_space_ldl_le(&s->dram_as,
> s->regs[R_DMA_DRAM_ADDR],
> > + data = address_space_ldl_le(&s->dram_as, dram_addr,
> >
> MEMTXATTRS_UNSPECIFIED, &result);
> > if (result != MEMTX_OK) {
> > - aspeed_smc_error("DRAM read failed @%08x",
> > - s->regs[R_DMA_DRAM_ADDR]);
> > + aspeed_smc_error("DRAM read failed @%" PRIx64,
> > + dram_addr);
> > return;
> > }
> >
> > @@ -913,11 +964,10 @@ static void aspeed_smc_dma_rw(AspeedSMCState
> *s)
> > return;
> > }
> >
> > - address_space_stl_le(&s->dram_as,
> s->regs[R_DMA_DRAM_ADDR],
> > + address_space_stl_le(&s->dram_as, dram_addr,
> > data,
> MEMTXATTRS_UNSPECIFIED, &result);
> > if (result != MEMTX_OK) {
> > - aspeed_smc_error("DRAM write failed @%08x",
> > - s->regs[R_DMA_DRAM_ADDR]);
> > + aspeed_smc_error("DRAM write failed @%" PRIx64,
> > + dram_addr);
> > return;
> > }
> > }
> > @@ -926,10 +976,18 @@ static void aspeed_smc_dma_rw(AspeedSMCState
> *s)
> > * When the DMA is on-going, the DMA registers are updated
> > * with the current working addresses and length.
> > */
> > + dram_addr += 4;
> > + dma_dram_addr += 4;
> > + if (aspeed_smc_has_dma_dram_addr_high(asc)) {
> > + dram_addr_high = dma_dram_addr >> 32;
> > + s->regs[R_DMA_DRAM_ADDR_HIGH] = dram_addr_high;
> > + }
> > +
> > + s->regs[R_DMA_DRAM_ADDR] = dma_dram_addr & 0xffffffff;
> > s->regs[R_DMA_FLASH_ADDR] += 4;
> > - s->regs[R_DMA_DRAM_ADDR] += 4;
> > - s->regs[R_DMA_LEN] -= 4;
> > s->regs[R_DMA_CHECKSUM] += data;
> > + dma_len -= 4;
> > + s->regs[R_DMA_LEN] = dma_len;
> > }
> > }
> >
> > @@ -1079,6 +1137,10 @@ static void aspeed_smc_write(void *opaque,
> hwaddr addr, uint64_t data,
> > } else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN &&
> > aspeed_smc_dma_granted(s)) {
> > s->regs[addr] = DMA_LENGTH(value);
> > + } else if (aspeed_smc_has_dma(asc) &&
> > + aspeed_smc_has_dma_dram_addr_high(asc) &&
> > + addr == R_DMA_DRAM_ADDR_HIGH) {
> > + s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
> > } else {
> > qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%"
> HWADDR_PRIx "\n",
> > __func__, addr); @@ -1372,6 +1434,7 @@
> static
> > void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data)
> > asc->features = ASPEED_SMC_FEATURE_DMA;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x1FFFFFFC;
> > + asc->dma_start_length = 4;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_smc_reg_to_segment;
> > @@ -1439,7 +1502,7 @@ static void
> aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
> > DeviceClass *dc = DEVICE_CLASS(klass);
> > AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> >
> > - dc->desc = "Aspeed 2600 FMC Controller";
> > + dc->desc = "Aspeed 2500 FMC Controller";
> > asc->r_conf = R_CONF;
> > asc->r_ce_ctrl = R_CE_CTRL;
> > asc->r_ctrl0 = R_CTRL0;
> > @@ -1455,6 +1518,7 @@ static void
> aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
> > asc->features = ASPEED_SMC_FEATURE_DMA;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x3FFFFFFC;
> > + asc->dma_start_length = 4;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_smc_reg_to_segment;
> > @@ -1477,7 +1541,7 @@ static void
> aspeed_2500_spi1_class_init(ObjectClass *klass, void *data)
> > DeviceClass *dc = DEVICE_CLASS(klass);
> > AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> >
> > - dc->desc = "Aspeed 2600 SPI1 Controller";
> > + dc->desc = "Aspeed 2500 SPI1 Controller";
> > asc->r_conf = R_CONF;
> > asc->r_ce_ctrl = R_CE_CTRL;
> > asc->r_ctrl0 = R_CTRL0;
> > @@ -1512,7 +1576,7 @@ static void
> aspeed_2500_spi2_class_init(ObjectClass *klass, void *data)
> > DeviceClass *dc = DEVICE_CLASS(klass);
> > AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> >
> > - dc->desc = "Aspeed 2600 SPI2 Controller";
> > + dc->desc = "Aspeed 2500 SPI2 Controller";
> > asc->r_conf = R_CONF;
> > asc->r_ce_ctrl = R_CE_CTRL;
> > asc->r_ctrl0 = R_CTRL0;
> > @@ -1611,6 +1675,7 @@ static void
> aspeed_2600_fmc_class_init(ObjectClass *klass, void *data)
> >
> ASPEED_SMC_FEATURE_WDT_CONTROL;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x3FFFFFFC;
> > + asc->dma_start_length = 1;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> > @@ -1649,6 +1714,7 @@ static void
> aspeed_2600_spi1_class_init(ObjectClass *klass, void *data)
> >
> ASPEED_SMC_FEATURE_DMA_GRANT;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x3FFFFFFC;
> > + asc->dma_start_length = 1;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> > @@ -1688,6 +1754,7 @@ static void
> aspeed_2600_spi2_class_init(ObjectClass *klass, void *data)
> >
> ASPEED_SMC_FEATURE_DMA_GRANT;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x3FFFFFFC;
> > + asc->dma_start_length = 1;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> > @@ -1769,6 +1836,7 @@ static void
> aspeed_1030_fmc_class_init(ObjectClass *klass, void *data)
> > asc->features = ASPEED_SMC_FEATURE_DMA;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x000BFFFC;
> > + asc->dma_start_length = 1;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_1030_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_1030_smc_reg_to_segment;
> > @@ -1806,6 +1874,7 @@ static void
> aspeed_1030_spi1_class_init(ObjectClass *klass, void *data)
> > asc->features = ASPEED_SMC_FEATURE_DMA;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x000BFFFC;
> > + asc->dma_start_length = 1;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> > @@ -1842,6 +1911,7 @@ static void
> aspeed_1030_spi2_class_init(ObjectClass *klass, void *data)
> > asc->features = ASPEED_SMC_FEATURE_DMA;
> > asc->dma_flash_mask = 0x0FFFFFFC;
> > asc->dma_dram_mask = 0x000BFFFC;
> > + asc->dma_start_length = 1;
> > asc->nregs = ASPEED_SMC_R_MAX;
> > asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> > asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> > @@ -1854,6 +1924,220 @@ static const TypeInfo aspeed_1030_spi2_info = {
> > .class_init = aspeed_1030_spi2_class_init,
> > };
> >
> > +/*
> > + * The FMC Segment Registers of the AST2700 have a 64KB unit.
> > + * Only bits [31:16] are used for decoding.
> > + */
> > +#define AST2700_SEG_ADDR_MASK 0xffff0000
> > +
> > +static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState
> *s,
> > + const
> AspeedSegments
> > +*seg) {
> > + uint32_t reg = 0;
> > +
> > + /* Disabled segments have a nil register */
> > + if (!seg->size) {
> > + return 0;
> > + }
> > +
> > + reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset
> */
> > + reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /*
> end offset */
> > + return reg;
> > +}
> > +
> > +static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s,
> > + uint32_t reg,
> > +AspeedSegments *seg) {
> > + uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK;
> > + uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK;
> > + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> > +
> > + if (reg) {
> > + seg->addr = asc->flash_window_base + start_offset;
> > + seg->size = end_offset + (64 * KiB) - start_offset;
> > + } else {
> > + seg->addr = asc->flash_window_base;
> > + seg->size = 0;
> > + }
> > +}
> > +
> > +static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = {
> > + [R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 |
> > + CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1),
> > + [R_CE_CTRL] = 0x0000aa00,
> > + [R_CTRL0] = 0x406b0641,
> > + [R_CTRL1] = 0x00000400,
> > + [R_CTRL2] = 0x00000400,
> > + [R_CTRL3] = 0x00000400,
> > + [R_SEG_ADDR0] = 0x08000000,
> > + [R_SEG_ADDR1] = 0x10000800,
> > + [R_SEG_ADDR2] = 0x00000000,
> > + [R_SEG_ADDR3] = 0x00000000,
> > + [R_DUMMY_DATA] = 0x00010000,
> > + [R_DMA_DRAM_ADDR_HIGH] = 0x00000000,
> > + [R_TIMINGS] = 0x007b0000,
> > +};
> > +
> > +static const AspeedSegments aspeed_2700_fmc_segments[] = {
> > + { 0x0, 128 * MiB }, /* start address is readonly */
> > + { 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel
> */
> > + { 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel
> */
> > + { 0x0, 0 }, /* disabled */
> > +};
> > +
> > +static void aspeed_2700_fmc_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> > +
> > + dc->desc = "Aspeed 2700 FMC Controller";
> > + asc->r_conf = R_CONF;
> > + asc->r_ce_ctrl = R_CE_CTRL;
> > + asc->r_ctrl0 = R_CTRL0;
> > + asc->r_timings = R_TIMINGS;
> > + asc->nregs_timings = 3;
> > + asc->conf_enable_w0 = CONF_ENABLE_W0;
> > + asc->cs_num_max = 3;
> > + asc->segments = aspeed_2700_fmc_segments;
> > + asc->segment_addr_mask = 0xffffffff;
> > + asc->resets = aspeed_2700_fmc_resets;
> > + asc->flash_window_base = 0x100000000;
> > + asc->flash_window_size = 1 * GiB;
> > + asc->features = ASPEED_SMC_FEATURE_DMA |
> > +
> ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> > + asc->dma_flash_mask = 0x2FFFFFFC;
> > + asc->dma_dram_mask = 0xFFFFFFFC;
> > + asc->dma_start_length = 1;
> > + asc->nregs = ASPEED_SMC_R_MAX;
> > + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> > + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> > + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> > +}
> > +
> > +static const TypeInfo aspeed_2700_fmc_info = {
> > + .name = "aspeed.fmc-ast2700",
> > + .parent = TYPE_ASPEED_SMC,
> > + .class_init = aspeed_2700_fmc_class_init, };
> > +
> > +static const AspeedSegments aspeed_2700_spi0_segments[] = {
> > + { 0x0, 128 * MiB }, /* start address is readonly */
> > + { 128 * MiB, 128 * MiB }, /* start address is readonly */
> > + { 0x0, 0 }, /* disabled */
> > +};
> > +
> > +static void aspeed_2700_spi0_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> > +
> > + dc->desc = "Aspeed 2700 SPI0 Controller";
> > + asc->r_conf = R_CONF;
> > + asc->r_ce_ctrl = R_CE_CTRL;
> > + asc->r_ctrl0 = R_CTRL0;
> > + asc->r_timings = R_TIMINGS;
> > + asc->nregs_timings = 2;
> > + asc->conf_enable_w0 = CONF_ENABLE_W0;
> > + asc->cs_num_max = 2;
> > + asc->segments = aspeed_2700_spi0_segments;
> > + asc->segment_addr_mask = 0xffffffff;
> > + asc->flash_window_base = 0x180000000;
> > + asc->flash_window_size = 1 * GiB;
> > + asc->features = ASPEED_SMC_FEATURE_DMA |
> > +
> ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> > + asc->dma_flash_mask = 0x2FFFFFFC;
> > + asc->dma_dram_mask = 0xFFFFFFFC;
> > + asc->dma_start_length = 1;
> > + asc->nregs = ASPEED_SMC_R_MAX;
> > + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> > + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> > + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> > +}
> > +
> > +static const TypeInfo aspeed_2700_spi0_info = {
> > + .name = "aspeed.spi0-ast2700",
> > + .parent = TYPE_ASPEED_SMC,
> > + .class_init = aspeed_2700_spi0_class_init, };
> > +
> > +static const AspeedSegments aspeed_2700_spi1_segments[] = {
> > + { 0x0, 128 * MiB }, /* start address is readonly */
> > + { 0x0, 0 }, /* disabled */
> > +};
> > +
> > +static void aspeed_2700_spi1_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> > +
> > + dc->desc = "Aspeed 2700 SPI1 Controller";
> > + asc->r_conf = R_CONF;
> > + asc->r_ce_ctrl = R_CE_CTRL;
> > + asc->r_ctrl0 = R_CTRL0;
> > + asc->r_timings = R_TIMINGS;
> > + asc->nregs_timings = 2;
> > + asc->conf_enable_w0 = CONF_ENABLE_W0;
> > + asc->cs_num_max = 2;
> > + asc->segments = aspeed_2700_spi1_segments;
> > + asc->segment_addr_mask = 0xffffffff;
> > + asc->flash_window_base = 0x200000000;
> > + asc->flash_window_size = 1 * GiB;
> > + asc->features = ASPEED_SMC_FEATURE_DMA |
> > +
> ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> > + asc->dma_flash_mask = 0x2FFFFFFC;
> > + asc->dma_dram_mask = 0xFFFFFFFC;
> > + asc->dma_start_length = 1;
> > + asc->nregs = ASPEED_SMC_R_MAX;
> > + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> > + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> > + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> > +}
> > +
> > +static const TypeInfo aspeed_2700_spi1_info = {
> > + .name = "aspeed.spi1-ast2700",
> > + .parent = TYPE_ASPEED_SMC,
> > + .class_init = aspeed_2700_spi1_class_init, };
> > +
> > +static const AspeedSegments aspeed_2700_spi2_segments[] = {
> > + { 0x0, 128 * MiB }, /* start address is readonly */
> > + { 0x0, 0 }, /* disabled */
> > +};
> > +
> > +static void aspeed_2700_spi2_class_init(ObjectClass *klass, void
> > +*data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
> > +
> > + dc->desc = "Aspeed 2700 SPI2 Controller";
> > + asc->r_conf = R_CONF;
> > + asc->r_ce_ctrl = R_CE_CTRL;
> > + asc->r_ctrl0 = R_CTRL0;
> > + asc->r_timings = R_TIMINGS;
> > + asc->nregs_timings = 2;
> > + asc->conf_enable_w0 = CONF_ENABLE_W0;
> > + asc->cs_num_max = 2;
> > + asc->segments = aspeed_2700_spi2_segments;
> > + asc->segment_addr_mask = 0xffffffff;
> > + asc->flash_window_base = 0x280000000;
> > + asc->flash_window_size = 1 * GiB;
> > + asc->features = ASPEED_SMC_FEATURE_DMA |
> > +
> ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
> > + asc->dma_flash_mask = 0x0FFFFFFC;
> > + asc->dma_dram_mask = 0xFFFFFFFC;
> > + asc->dma_start_length = 1;
> > + asc->nregs = ASPEED_SMC_R_MAX;
> > + asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
> > + asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
> > + asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
> > +}
> > +
> > +static const TypeInfo aspeed_2700_spi2_info = {
> > + .name = "aspeed.spi2-ast2700",
> > + .parent = TYPE_ASPEED_SMC,
> > + .class_init = aspeed_2700_spi2_class_init, };
> > +
> > static void aspeed_smc_register_types(void)
> > {
> > type_register_static(&aspeed_smc_flash_info);
> > @@ -1870,6 +2154,10 @@ static void aspeed_smc_register_types(void)
> > type_register_static(&aspeed_1030_fmc_info);
> > type_register_static(&aspeed_1030_spi1_info);
> > type_register_static(&aspeed_1030_spi2_info);
> > + type_register_static(&aspeed_2700_fmc_info);
> > + type_register_static(&aspeed_2700_spi0_info);
> > + type_register_static(&aspeed_2700_spi1_info);
> > + type_register_static(&aspeed_2700_spi2_info);
> > }
> >
> > type_init(aspeed_smc_register_types)
> > diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events index
> > 2d5bd2b83d..7b5ad6a939 100644
> > --- a/hw/ssi/trace-events
> > +++ b/hw/ssi/trace-events
> > @@ -6,7 +6,7 @@ aspeed_smc_do_snoop(int cs, int index, int dummies, int
> data) "CS%d index:0x%x d
> > aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t
> data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
> > aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
> PRIx64 " size %u: 0x%" PRIx64
> > aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x:
> 0x%08x"
> > -aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t
> dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
> > +aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint64_t
> dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%" PRIx64 "
> size:0x%08x"
> > aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
> PRIx64 " size %u: 0x%" PRIx64
> > aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
> >
> > diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> > index 8e1dda556b..f359ed22cc 100644
> > --- a/include/hw/ssi/aspeed_smc.h
> > +++ b/include/hw/ssi/aspeed_smc.h
> > @@ -106,6 +106,7 @@ struct AspeedSMCClass {
> > uint32_t features;
> > hwaddr dma_flash_mask;
> > hwaddr dma_dram_mask;
> > + uint32_t dma_start_length;
> > uint32_t nregs;
> > uint32_t (*segment_to_reg)(const AspeedSMCState *s,
> > const AspeedSegments *seg);
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2024-03-12 9:59 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-04 9:29 [PATCH v2 0/9] Add AST2700 support Jamin Lin via
2024-03-04 9:29 ` [PATCH v2 3/9] aspeed/sdmc: " Jamin Lin via
2024-03-04 14:47 ` Cédric Le Goater
2024-03-11 7:21 ` Jamin Lin
2024-03-11 14:57 ` Cédric Le Goater
2024-03-12 3:42 ` Jamin Lin
2024-03-04 9:29 ` [PATCH v2 4/9] aspeed/smc: " Jamin Lin via
2024-03-04 15:19 ` Cédric Le Goater
2024-03-12 9:58 ` Jamin Lin
2024-03-04 9:29 ` [PATCH v2 5/9] aspeed/scu: " Jamin Lin via
2024-03-04 15:37 ` Cédric Le Goater
2024-03-04 9:29 ` [PATCH v2 6/9] aspeed/intc: " Jamin Lin via
[not found] ` <20240304092934.1953198-2-jamin_lin@aspeedtech.com>
2024-03-04 14:32 ` [PATCH v2 1/9] aspeed/wdt: " Cédric Le Goater
2024-03-05 3:08 ` Jamin Lin
[not found] ` <20240304092934.1953198-3-jamin_lin@aspeedtech.com>
2024-03-04 14:36 ` [PATCH v2 2/9] aspeed/sli: " Cédric Le Goater
2024-03-05 3:28 ` Jamin Lin
[not found] ` <20240304092934.1953198-9-jamin_lin@aspeedtech.com>
2024-03-04 15:39 ` [PATCH v2 8/9] aspeed: Add an AST2700 eval board Cédric Le Goater
2024-03-05 5:08 ` Jamin Lin
[not found] ` <20240304092934.1953198-8-jamin_lin@aspeedtech.com>
2024-03-04 15:49 ` [PATCH v2 7/9] aspeed/soc: Add AST2700 support Cédric Le Goater
2024-03-11 10:31 ` Jamin Lin
2024-03-04 15:54 ` [PATCH v2 0/9] " Cédric Le Goater
2024-03-05 3:38 ` Jamin Lin
2024-03-07 10:42 ` Cédric Le Goater
2024-03-11 1:14 ` Jamin Lin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).