aspeed queue:

* Add AST2700 support
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmZvtLUACgkQUaNDx8/7
 7KH8Ew/+K7OJYUsRhuLByLjaQ8kCsVdxMCFLtpCL9t6AgrMUXaI6WkkynPMKITQQ
 AHocO76TsWRMp962obnjvXgVRCrtvOI2W5jvgp1Gr554tW7YQClLiGhuf1FeORS9
 ZQhWryoC8vK8ymC7dAS5cyuiddWFUGC04P9lb9oXr88n6goZ1xRfKwM+RttgfCAm
 79SsK7g3TS8QOWH1kQwIQZyJKzwrw7bTM3Ijv9NmVKa050zWquMRZQeY18fgO6Ae
 p/pGpkf4Bc5iv+kIXoI4UN7Cx74aZoKInQ+DA71gtCWh/s09j9PkvOAfKWYAozD+
 VSaLvw4rvhRxgbs1SjoiMb5dDjJhngfzLhJX/P2FD1LCHRk+/uxk3fDDp2AqvQ6z
 IuWPb8FgWHqeiigcXkTW1JgUS85quIbjWBxreIrQiq+zR50EQy49elMRhzJlKsqZ
 3/ulk7xf+5M1+wS4bo7r8LPk5K8mFw9b4cxfnx0feZCjrl4ZfeWyDtaKzCAU0MJq
 KfpHo9R98imjVmcRWUouTaFow33OXheLdPFO8PofVnT38a4KIWlkin3zFMdTOAk+
 f8kWMPlXlRpKBYsjvP2aCpoY6CY8bHskdBH7xysM2W1FfKTw3dwZRpt4dgVPxqYj
 KZXiKxzwnC2gGi/wn+EdhZwYy1nNSZYGK8s+jxBXi2UBrwv4PpA=
 =TnR8
 -----END PGP SIGNATURE-----

Merge tag 'pull-aspeed-20240617' of https://github.com/legoater/qemu into staging

aspeed queue:

* Add AST2700 support

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmZvtLUACgkQUaNDx8/7
# 7KH8Ew/+K7OJYUsRhuLByLjaQ8kCsVdxMCFLtpCL9t6AgrMUXaI6WkkynPMKITQQ
# AHocO76TsWRMp962obnjvXgVRCrtvOI2W5jvgp1Gr554tW7YQClLiGhuf1FeORS9
# ZQhWryoC8vK8ymC7dAS5cyuiddWFUGC04P9lb9oXr88n6goZ1xRfKwM+RttgfCAm
# 79SsK7g3TS8QOWH1kQwIQZyJKzwrw7bTM3Ijv9NmVKa050zWquMRZQeY18fgO6Ae
# p/pGpkf4Bc5iv+kIXoI4UN7Cx74aZoKInQ+DA71gtCWh/s09j9PkvOAfKWYAozD+
# VSaLvw4rvhRxgbs1SjoiMb5dDjJhngfzLhJX/P2FD1LCHRk+/uxk3fDDp2AqvQ6z
# IuWPb8FgWHqeiigcXkTW1JgUS85quIbjWBxreIrQiq+zR50EQy49elMRhzJlKsqZ
# 3/ulk7xf+5M1+wS4bo7r8LPk5K8mFw9b4cxfnx0feZCjrl4ZfeWyDtaKzCAU0MJq
# KfpHo9R98imjVmcRWUouTaFow33OXheLdPFO8PofVnT38a4KIWlkin3zFMdTOAk+
# f8kWMPlXlRpKBYsjvP2aCpoY6CY8bHskdBH7xysM2W1FfKTw3dwZRpt4dgVPxqYj
# KZXiKxzwnC2gGi/wn+EdhZwYy1nNSZYGK8s+jxBXi2UBrwv4PpA=
# =TnR8
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 16 Jun 2024 08:59:49 PM PDT
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* tag 'pull-aspeed-20240617' of https://github.com/legoater/qemu:
  MAINTAINERS: Add reviewers for ASPEED BMCs
  docs:aspeed: Add AST2700 Evaluation board
  test/avocado/machine_aspeed.py: Add AST2700 test case
  aspeed/soc: fix incorrect dram size for AST2700
  aspeed: Add an AST2700 eval board
  aspeed/soc: Add AST2700 support
  aspeed/intc: Add AST2700 support
  aspeed/scu: Add AST2700 support
  aspeed/smc: Add AST2700 support
  aspeed/smc: support different memory region ops for SMC flash region
  aspeed/smc: support 64 bits dma dram address
  aspeed/smc: support dma start length and 1 byte length unit
  aspeed/smc: correct device description
  aspeed/sdmc: Add AST2700 support
  aspeed/sdmc: fix coding style
  aspeed/sdmc: remove redundant macros
  aspeed/sli: Add AST2700 support
  aspeed/wdt: Add AST2700 support
  aspeed/smc: Reintroduce "dram-base" property for AST2700

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-06-17 09:20:05 -07:00
commit 79e6ec66ba
24 changed files with 2351 additions and 58 deletions

View File

@ -1158,6 +1158,9 @@ F: docs/system/arm/emcraft-sf2.rst
ASPEED BMCs ASPEED BMCs
M: Cédric Le Goater <clg@kaod.org> M: Cédric Le Goater <clg@kaod.org>
M: Peter Maydell <peter.maydell@linaro.org> M: Peter Maydell <peter.maydell@linaro.org>
R: Steven Lee <steven_lee@aspeedtech.com>
R: Troy Lee <leetroy@gmail.com>
R: Jamin Lin <jamin_lin@aspeedtech.com>
R: Andrew Jeffery <andrew@codeconstruct.com.au> R: Andrew Jeffery <andrew@codeconstruct.com.au>
R: Joel Stanley <joel@jms.id.au> R: Joel Stanley <joel@jms.id.au>
L: qemu-arm@nongnu.org L: qemu-arm@nongnu.org

View File

@ -1,11 +1,12 @@
Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``) Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``)
================================================================== ===================================================================================
The QEMU Aspeed machines model BMCs of various OpenPOWER systems and The QEMU Aspeed machines model BMCs of various OpenPOWER systems and
Aspeed evaluation boards. They are based on different releases of the Aspeed evaluation boards. They are based on different releases of the
Aspeed SoC : the AST2400 integrating an ARM926EJ-S CPU (400MHz), the Aspeed SoC : the AST2400 integrating an ARM926EJ-S CPU (400MHz), the
AST2500 with an ARM1176JZS CPU (800MHz) and more recently the AST2600 AST2500 with an ARM1176JZS CPU (800MHz), the AST2600
with dual cores ARM Cortex-A7 CPUs (1.2GHz). with dual cores ARM Cortex-A7 CPUs (1.2GHz) and more recently the AST2700
with quad cores ARM Cortex-A35 64 bits CPUs (1.6GHz)
The SoC comes with RAM, Gigabit ethernet, USB, SD/MMC, USB, SPI, I2C, The SoC comes with RAM, Gigabit ethernet, USB, SD/MMC, USB, SPI, I2C,
etc. etc.
@ -38,6 +39,10 @@ AST2600 SoC based machines :
- ``qcom-dc-scm-v1-bmc`` Qualcomm DC-SCM V1 BMC - ``qcom-dc-scm-v1-bmc`` Qualcomm DC-SCM V1 BMC
- ``qcom-firework-bmc`` Qualcomm Firework BMC - ``qcom-firework-bmc`` Qualcomm Firework BMC
AST2700 SoC based machines :
- ``ast2700-evb`` Aspeed AST2700 Evaluation board (Cortex-A35)
Supported devices Supported devices
----------------- -----------------
@ -66,6 +71,7 @@ Supported devices
* eMMC Boot Controller (dummy) * eMMC Boot Controller (dummy)
* PECI Controller (minimal) * PECI Controller (minimal)
* I3C Controller * I3C Controller
* Internal Bridge Controller (SLI dummy)
Missing devices Missing devices
@ -95,6 +101,10 @@ or directly from the OpenBMC GitHub release repository :
https://github.com/openbmc/openbmc/releases https://github.com/openbmc/openbmc/releases
or directly from the ASPEED Forked OpenBMC GitHub release repository :
https://github.com/AspeedTech-BMC/openbmc/releases
To boot a kernel directly from a Linux build tree: To boot a kernel directly from a Linux build tree:
.. code-block:: bash .. code-block:: bash
@ -164,6 +174,27 @@ under Linux), use :
-M ast2500-evb,bmc-console=uart3 -M ast2500-evb,bmc-console=uart3
Boot the AST2700 machine from the flash image, use an MTD drive :
.. code-block:: bash
IMGDIR=ast2700-default
UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
$ qemu-system-aarch64 -M ast2700-evb \
-device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin \
-device loader,force-raw=on,addr=$((0x400000000 + ${UBOOT_SIZE})),file=${IMGDIR}/u-boot.dtb \
-device loader,force-raw=on,addr=0x430000000,file=${IMGDIR}/bl31.bin \
-device loader,force-raw=on,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin \
-device loader,cpu-num=0,addr=0x430000000 \
-device loader,cpu-num=1,addr=0x430000000 \
-device loader,cpu-num=2,addr=0x430000000 \
-device loader,cpu-num=3,addr=0x430000000 \
-smp 4 \
-drive file=${IMGDIR}/image-bmc,format=raw,if=mtd \
-nographic
Aspeed minibmc family boards (``ast1030-evb``) Aspeed minibmc family boards (``ast1030-evb``)
================================================================== ==================================================================

View File

@ -178,6 +178,12 @@ struct AspeedMachineState {
#define AST2600_EVB_HW_STRAP1 0x000000C0 #define AST2600_EVB_HW_STRAP1 0x000000C0
#define AST2600_EVB_HW_STRAP2 0x00000003 #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 */ /* Tacoma hardware value */
#define TACOMA_BMC_HW_STRAP1 0x00000000 #define TACOMA_BMC_HW_STRAP1 0x00000000
#define TACOMA_BMC_HW_STRAP2 0x00000040 #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); 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;
aspeed_machine_class_init_cpus_defaults(mc);
}
#endif
static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc, static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
void *data) void *data)
{ {
@ -1711,6 +1737,12 @@ static const TypeInfo aspeed_machine_types[] = {
.name = MACHINE_TYPE_NAME("ast1030-evb"), .name = MACHINE_TYPE_NAME("ast1030-evb"),
.parent = TYPE_ASPEED_MACHINE, .parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_minibmc_machine_ast1030_evb_class_init, .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, .name = TYPE_ASPEED_MACHINE,
.parent = TYPE_MACHINE, .parent = TYPE_MACHINE,

648
hw/arm/aspeed_ast27x0.c Normal file
View File

@ -0,0 +1,648 @@
/*
* 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"
#include "qemu/log.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_INTC] = 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,
};
/* GICINT 128 */
static const int aspeed_soc_ast2700_gic128_intcmap[] = {
[ASPEED_DEV_LPC] = 0,
[ASPEED_DEV_IBT] = 2,
[ASPEED_DEV_KCS] = 4,
};
/* GICINT 130 */
static const int aspeed_soc_ast2700_gic130_intcmap[] = {
[ASPEED_DEV_I2C] = 0,
[ASPEED_DEV_ADC] = 16,
[ASPEED_DEV_GPIO_1_8V] = 18,
};
/* GICINT 131 */
static const int aspeed_soc_ast2700_gic131_intcmap[] = {
[ASPEED_DEV_I3C] = 0,
[ASPEED_DEV_WDT] = 16,
[ASPEED_DEV_FMC] = 25,
[ASPEED_DEV_PWM] = 29,
};
/* GICINT 132 */
static const int aspeed_soc_ast2700_gic132_intcmap[] = {
[ASPEED_DEV_ETH1] = 0,
[ASPEED_DEV_ETH2] = 1,
[ASPEED_DEV_ETH3] = 2,
[ASPEED_DEV_UART0] = 7,
[ASPEED_DEV_UART1] = 8,
[ASPEED_DEV_UART2] = 9,
[ASPEED_DEV_UART3] = 10,
[ASPEED_DEV_UART5] = 11,
[ASPEED_DEV_UART6] = 12,
[ASPEED_DEV_UART7] = 13,
[ASPEED_DEV_UART8] = 14,
[ASPEED_DEV_UART9] = 15,
[ASPEED_DEV_UART10] = 16,
[ASPEED_DEV_UART11] = 17,
[ASPEED_DEV_UART12] = 18,
};
/* GICINT 133 */
static const int aspeed_soc_ast2700_gic133_intcmap[] = {
[ASPEED_DEV_PECI] = 4,
};
/* GICINT 128 ~ 136 */
struct gic_intc_irq_info {
int irq;
const int *ptr;
};
static const struct gic_intc_irq_info aspeed_soc_ast2700_gic_intcmap[] = {
{128, aspeed_soc_ast2700_gic128_intcmap},
{129, NULL},
{130, aspeed_soc_ast2700_gic130_intcmap},
{131, aspeed_soc_ast2700_gic131_intcmap},
{132, aspeed_soc_ast2700_gic132_intcmap},
{133, aspeed_soc_ast2700_gic133_intcmap},
{134, NULL},
{135, NULL},
{136, NULL},
};
static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
{
Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
int i;
for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
aspeed_soc_ast2700_gic_intcmap[i].ptr[dev]);
}
}
return qdev_get_gpio_in(DEVICE(&a->gic), sc->irqmap[dev]);
}
static uint64_t aspeed_ram_capacity_read(void *opaque, hwaddr addr,
unsigned int size)
{
qemu_log_mask(LOG_GUEST_ERROR,
"%s: DRAM read out of ram size, addr:0x%" PRIx64 "\n",
__func__, addr);
return 0;
}
static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
AspeedSoCState *s = ASPEED_SOC(opaque);
ram_addr_t ram_size;
MemTxResult result;
ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size",
&error_abort);
/*
* Emulate ddr capacity hardware behavior.
* If writes the data to the address which is beyond the ram size,
* it would write the data to the "address % ram_size".
*/
result = address_space_write(&s->dram_as, addr % ram_size,
MEMTXATTRS_UNSPECIFIED, &data, 4);
if (result != MEMTX_OK) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: DRAM write failed, addr:0x%" HWADDR_PRIx
", data :0x%" PRIx64 "\n",
__func__, addr % ram_size, data);
}
}
static const MemoryRegionOps aspeed_ram_capacity_ops = {
.read = aspeed_ram_capacity_read,
.write = aspeed_ram_capacity_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 8,
},
};
/*
* SDMC should be realized first to get correct RAM size and max size
* values
*/
static bool aspeed_soc_ast2700_dram_init(DeviceState *dev, Error **errp)
{
ram_addr_t ram_size, max_ram_size;
Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
AspeedSoCState *s = ASPEED_SOC(dev);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size",
&error_abort);
max_ram_size = object_property_get_uint(OBJECT(&s->sdmc), "max-ram-size",
&error_abort);
memory_region_init(&s->dram_container, OBJECT(s), "ram-container",
ram_size);
memory_region_add_subregion(&s->dram_container, 0, s->dram_mr);
address_space_init(&s->dram_as, s->dram_mr, "dram");
/*
* Add a memory region beyond the RAM region to emulate
* ddr capacity hardware behavior.
*/
if (ram_size < max_ram_size) {
memory_region_init_io(&a->dram_empty, OBJECT(s),
&aspeed_ram_capacity_ops, s,
"ram-empty", max_ram_size - ram_size);
memory_region_add_subregion(s->memory,
sc->memmap[ASPEED_DEV_SDRAM] + ram_size,
&a->dram_empty);
}
memory_region_add_subregion(s->memory,
sc->memmap[ASPEED_DEV_SDRAM], &s->dram_container);
return true;
}
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, "gic", &a->gic, gicv3_class_name());
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_2700_INTC);
}
/*
* ASPEED ast2700 has 0x0 as cluster ID
*
* https://developer.arm.com/documentation/100236/0100/register-descriptions/aarch64-system-registers/multiprocessor-affinity-register--el1
*/
static uint64_t aspeed_calc_affinity(int cpu)
{
return (0x0 << ARM_AFF1_SHIFT) | cpu;
}
static bool aspeed_soc_ast2700_gic_realize(DeviceState *dev, Error **errp)
{
Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
AspeedSoCState *s = ASPEED_SOC(dev);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
SysBusDevice *gicbusdev;
DeviceState *gicdev;
QList *redist_region_count;
int i;
gicbusdev = SYS_BUS_DEVICE(&a->gic);
gicdev = DEVICE(&a->gic);
qdev_prop_set_uint32(gicdev, "revision", 3);
qdev_prop_set_uint32(gicdev, "num-cpu", sc->num_cpus);
qdev_prop_set_uint32(gicdev, "num-irq", AST2700_MAX_IRQ);
redist_region_count = qlist_new();
qlist_append_int(redist_region_count, sc->num_cpus);
qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
if (!sysbus_realize(gicbusdev, errp)) {
return false;
}
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(&a->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(gicdev, ppibase + timer_irq[j]));
}
qemu_irq irq = qdev_get_gpio_in(gicdev,
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(gicdev, 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));
}
return true;
}
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);
AspeedINTCClass *ic = ASPEED_INTC_GET_CLASS(&a->intc);
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 */
if (!aspeed_soc_ast2700_gic_realize(dev, errp)) {
return;
}
/* 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_INTC]);
/* GICINT orgates -> INTC -> GIC */
for (i = 0; i < ic->num_ints; i++) {
qdev_connect_gpio_out(DEVICE(&a->intc.orgates[i]), 0,
qdev_get_gpio_in(DEVICE(&a->intc), i));
sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), i,
qdev_get_gpio_in(DEVICE(&a->gic),
aspeed_soc_ast2700_gic_intcmap[i].irq));
}
/* 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_int(OBJECT(&s->fmc), "dram-base",
sc->memmap[ASPEED_DEV_SDRAM],
&error_abort);
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
* The SDMC controller is unlocked at SPL stage.
* At present, only supports to emulate booting
* start from u-boot stage. Set SDMC controller
* unlocked by default. It is a temporarily solution.
*/
object_property_set_bool(OBJECT(&s->sdmc), "unlocked", true,
&error_abort);
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_ast2700_dram_init(dev, 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);
/* Reason: The Aspeed SoC can only be instantiated from a board */
dc->user_creatable = false;
dc->realize = aspeed_soc_ast2700_realize;
sc->name = "ast2700-a0";
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2700_A0_SILICON_REV;
sc->sram_size = 0x20000;
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)

View File

@ -49,6 +49,7 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_ast10x0.c', 'aspeed_ast10x0.c',
'aspeed_eeprom.c', 'aspeed_eeprom.c',
'fby35.c')) 'fby35.c'))
arm_ss.add(when: ['CONFIG_ASPEED_SOC', 'TARGET_AARCH64'], if_true: files('aspeed_ast27x0.c'))
arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2.c')) arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2.c'))
arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2-tz.c')) arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2-tz.c'))
arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c')) arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))

361
hw/intc/aspeed_intc.c Normal file
View File

@ -0,0 +1,361 @@
/*
* ASPEED INTC Controller
*
* Copyright (C) 2024 ASPEED Technology Inc.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "hw/intc/aspeed_intc.h"
#include "hw/irq.h"
#include "qemu/log.h"
#include "trace.h"
#include "hw/registerfields.h"
#include "qapi/error.h"
/* INTC Registers */
REG32(GICINT128_EN, 0x1000)
REG32(GICINT128_STATUS, 0x1004)
REG32(GICINT129_EN, 0x1100)
REG32(GICINT129_STATUS, 0x1104)
REG32(GICINT130_EN, 0x1200)
REG32(GICINT130_STATUS, 0x1204)
REG32(GICINT131_EN, 0x1300)
REG32(GICINT131_STATUS, 0x1304)
REG32(GICINT132_EN, 0x1400)
REG32(GICINT132_STATUS, 0x1404)
REG32(GICINT133_EN, 0x1500)
REG32(GICINT133_STATUS, 0x1504)
REG32(GICINT134_EN, 0x1600)
REG32(GICINT134_STATUS, 0x1604)
REG32(GICINT135_EN, 0x1700)
REG32(GICINT135_STATUS, 0x1704)
REG32(GICINT136_EN, 0x1800)
REG32(GICINT136_STATUS, 0x1804)
#define GICINT_STATUS_BASE R_GICINT128_STATUS
static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
if (irq >= aic->num_ints) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
__func__, irq);
return;
}
trace_aspeed_intc_update_irq(irq, level);
qemu_set_irq(s->output_pins[irq], level);
}
/*
* The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
* Utilize "address & 0x0f00" to get the irq and irq output pin index
* The value of irq should be 0 to num_ints.
* The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
*/
static void aspeed_intc_set_irq(void *opaque, int irq, int level)
{
AspeedINTCState *s = (AspeedINTCState *)opaque;
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
uint32_t status_addr = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
uint32_t select = 0;
uint32_t enable;
int i;
if (irq >= aic->num_ints) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
__func__, irq);
return;
}
trace_aspeed_intc_set_irq(irq, level);
enable = s->enable[irq];
if (!level) {
return;
}
for (i = 0; i < aic->num_lines; i++) {
if (s->orgates[irq].levels[i]) {
if (enable & BIT(i)) {
select |= BIT(i);
}
}
}
if (!select) {
return;
}
trace_aspeed_intc_select(select);
if (s->mask[irq] || s->regs[status_addr]) {
/*
* a. mask is not 0 means in ISR mode
* sources interrupt routine are executing.
* b. status register value is not 0 means previous
* source interrupt does not be executed, yet.
*
* save source interrupt to pending variable.
*/
s->pending[irq] |= select;
trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
} else {
/*
* notify firmware which source interrupt are coming
* by setting status register
*/
s->regs[status_addr] = select;
trace_aspeed_intc_trigger_irq(irq, s->regs[status_addr]);
aspeed_intc_update(s, irq, 1);
}
}
static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
{
AspeedINTCState *s = ASPEED_INTC(opaque);
uint32_t addr = offset >> 2;
uint32_t value = 0;
if (addr >= ASPEED_INTC_NR_REGS) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
return 0;
}
value = s->regs[addr];
trace_aspeed_intc_read(offset, size, value);
return value;
}
static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
unsigned size)
{
AspeedINTCState *s = ASPEED_INTC(opaque);
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
uint32_t addr = offset >> 2;
uint32_t old_enable;
uint32_t change;
uint32_t irq;
if (addr >= ASPEED_INTC_NR_REGS) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
return;
}
trace_aspeed_intc_write(offset, size, data);
switch (addr) {
case R_GICINT128_EN:
case R_GICINT129_EN:
case R_GICINT130_EN:
case R_GICINT131_EN:
case R_GICINT132_EN:
case R_GICINT133_EN:
case R_GICINT134_EN:
case R_GICINT135_EN:
case R_GICINT136_EN:
irq = (offset & 0x0f00) >> 8;
if (irq >= aic->num_ints) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
__func__, irq);
return;
}
/*
* These registers are used for enable sources interrupt and
* mask and unmask source interrupt while executing source ISR.
*/
/* disable all source interrupt */
if (!data && !s->enable[irq]) {
s->regs[addr] = data;
return;
}
old_enable = s->enable[irq];
s->enable[irq] |= data;
/* enable new source interrupt */
if (old_enable != s->enable[irq]) {
trace_aspeed_intc_enable(s->enable[irq]);
s->regs[addr] = data;
return;
}
/* mask and unmask source interrupt */
change = s->regs[addr] ^ data;
if (change & data) {
s->mask[irq] &= ~change;
trace_aspeed_intc_unmask(change, s->mask[irq]);
} else {
s->mask[irq] |= change;
trace_aspeed_intc_mask(change, s->mask[irq]);
}
s->regs[addr] = data;
break;
case R_GICINT128_STATUS:
case R_GICINT129_STATUS:
case R_GICINT130_STATUS:
case R_GICINT131_STATUS:
case R_GICINT132_STATUS:
case R_GICINT133_STATUS:
case R_GICINT134_STATUS:
case R_GICINT135_STATUS:
case R_GICINT136_STATUS:
irq = (offset & 0x0f00) >> 8;
if (irq >= aic->num_ints) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
__func__, irq);
return;
}
/* clear status */
s->regs[addr] &= ~data;
/*
* These status registers are used for notify sources ISR are executed.
* If one source ISR is executed, it will clear one bit.
* If it clear all bits, it means to initialize this register status
* rather than sources ISR are executed.
*/
if (data == 0xffffffff) {
return;
}
/* All source ISR execution are done */
if (!s->regs[addr]) {
trace_aspeed_intc_all_isr_done(irq);
if (s->pending[irq]) {
/*
* handle pending source interrupt
* notify firmware which source interrupt are pending
* by setting status register
*/
s->regs[addr] = s->pending[irq];
s->pending[irq] = 0;
trace_aspeed_intc_trigger_irq(irq, s->regs[addr]);
aspeed_intc_update(s, irq, 1);
} else {
/* clear irq */
trace_aspeed_intc_clear_irq(irq, 0);
aspeed_intc_update(s, irq, 0);
}
}
break;
default:
s->regs[addr] = data;
break;
}
return;
}
static const MemoryRegionOps aspeed_intc_ops = {
.read = aspeed_intc_read,
.write = aspeed_intc_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
}
};
static void aspeed_intc_instance_init(Object *obj)
{
AspeedINTCState *s = ASPEED_INTC(obj);
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
assert(aic->num_ints <= ASPEED_INTC_NR_INTS);
for (i = 0; i < aic->num_ints; i++) {
object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
TYPE_OR_IRQ);
object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
aic->num_lines, &error_abort);
}
}
static void aspeed_intc_reset(DeviceState *dev)
{
AspeedINTCState *s = ASPEED_INTC(dev);
memset(s->regs, 0, sizeof(s->regs));
memset(s->enable, 0, sizeof(s->enable));
memset(s->mask, 0, sizeof(s->mask));
memset(s->pending, 0, sizeof(s->pending));
}
static void aspeed_intc_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
AspeedINTCState *s = ASPEED_INTC(dev);
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
sysbus_init_mmio(sbd, &s->iomem);
qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
for (i = 0; i < aic->num_ints; i++) {
if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
return;
}
sysbus_init_irq(sbd, &s->output_pins[i]);
}
}
static void aspeed_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->desc = "ASPEED INTC Controller";
dc->realize = aspeed_intc_realize;
dc->reset = aspeed_intc_reset;
dc->vmsd = NULL;
}
static const TypeInfo aspeed_intc_info = {
.name = TYPE_ASPEED_INTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_init = aspeed_intc_instance_init,
.instance_size = sizeof(AspeedINTCState),
.class_init = aspeed_intc_class_init,
.class_size = sizeof(AspeedINTCClass),
.abstract = true,
};
static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
dc->desc = "ASPEED 2700 INTC Controller";
aic->num_lines = 32;
aic->num_ints = 9;
}
static const TypeInfo aspeed_2700_intc_info = {
.name = TYPE_ASPEED_2700_INTC,
.parent = TYPE_ASPEED_INTC,
.class_init = aspeed_2700_intc_class_init,
};
static void aspeed_intc_register_types(void)
{
type_register_static(&aspeed_intc_info);
type_register_static(&aspeed_2700_intc_info);
}
type_init(aspeed_intc_register_types);

View File

@ -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_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_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_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_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c'))
system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c')) system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))

View File

@ -79,6 +79,19 @@ aspeed_vic_update_fiq(int flags) "Raising FIQ: %d"
aspeed_vic_update_irq(int flags) "Raising IRQ: %d" aspeed_vic_update_irq(int flags) "Raising IRQ: %d"
aspeed_vic_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_vic_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
# aspeed_intc.c
aspeed_intc_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_intc_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_intc_set_irq(int irq, int level) "Set IRQ %d: %d"
aspeed_intc_clear_irq(int irq, int level) "Clear IRQ %d: %d"
aspeed_intc_update_irq(int irq, int level) "Update IRQ: %d: %d"
aspeed_intc_pending_irq(int irq, uint32_t value) "Pending IRQ: %d: 0x%x"
aspeed_intc_trigger_irq(int irq, uint32_t value) "Trigger IRQ: %d: 0x%x"
aspeed_intc_all_isr_done(int irq) "All source ISR execution are done: %d"
aspeed_intc_enable(uint32_t value) "Enable: 0x%x"
aspeed_intc_select(uint32_t value) "Select: 0x%x"
aspeed_intc_mask(uint32_t change, uint32_t value) "Mask: 0x%x: 0x%x"
aspeed_intc_unmask(uint32_t change, uint32_t value) "UnMask: 0x%x: 0x%x"
# arm_gic.c # arm_gic.c
gic_enable_irq(int irq) "irq %d enabled" gic_enable_irq(int irq) "irq %d enabled"

View File

@ -134,6 +134,48 @@
#define AST2600_CLK TO_REG(0x40) #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 #define SCU_IO_REGION_SIZE 0x1000
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = { 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; / 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) static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
{ {
AspeedSCUState *s = ASPEED_SCU(opaque); AspeedSCUState *s = ASPEED_SCU(opaque);
@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
switch (reg) { switch (reg) {
case RNG_DATA: 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 * the state of the enable bit in RNG_CTRL
*/ */
s->regs[RNG_DATA] = aspeed_scu_get_random(); s->regs[RNG_DATA] = aspeed_scu_get_random();
@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
AST2600_A3_SILICON_REV, AST2600_A3_SILICON_REV,
AST1030_A0_SILICON_REV, AST1030_A0_SILICON_REV,
AST1030_A1_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) 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, .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: Unhandled 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: Unhandled 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] = { static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
[AST2600_SYS_RST_CTRL] = 0xFFC3FED8, [AST2600_SYS_RST_CTRL] = 0xFFC3FED8,
[AST2600_SYS_RST_CTRL2] = 0x09FFFFFC, [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_2500_scu_info);
type_register_static(&aspeed_2600_scu_info); type_register_static(&aspeed_2600_scu_info);
type_register_static(&aspeed_1030_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); type_init(aspeed_scu_register_types);

View File

@ -27,6 +27,7 @@
#define PROT_SOFTLOCKED 0x00 #define PROT_SOFTLOCKED 0x00
#define PROT_KEY_UNLOCK 0xFC600309 #define PROT_KEY_UNLOCK 0xFC600309
#define PROT_2700_KEY_UNLOCK 0x1688A8A8
#define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */ #define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
/* Configuration Register */ /* Configuration Register */
@ -54,6 +55,46 @@
#define R_DRAM_TIME (0x8c / 4) #define R_DRAM_TIME (0x8c / 4)
#define R_ECC_ERR_INJECT (0xb4 / 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) * Configuration register Ox4 (for Aspeed AST2400 SOC)
* *
@ -76,10 +117,6 @@
#define ASPEED_SDMC_VGA_32MB 0x2 #define ASPEED_SDMC_VGA_32MB 0x2
#define ASPEED_SDMC_VGA_64MB 0x3 #define ASPEED_SDMC_VGA_64MB 0x3
#define ASPEED_SDMC_DRAM_SIZE(x) (x & 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 \ #define ASPEED_SDMC_READONLY_MASK \
(ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \ (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
@ -100,22 +137,24 @@
#define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs from AST2400 */ #define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs from AST2400 */
#define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* 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 \ #define ASPEED_SDMC_AST2500_READONLY_MASK \
(ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \ (ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \
ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \ ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB)) 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) static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
{ {
AspeedSDMCState *s = ASPEED_SDMC(opaque); AspeedSDMCState *s = ASPEED_SDMC(opaque);
@ -231,7 +270,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
AspeedSDMCState *s = ASPEED_SDMC(dev); AspeedSDMCState *s = ASPEED_SDMC(dev);
AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */ assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
s->max_ram_size = asc->max_ram_size; s->max_ram_size = asc->max_ram_size;
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s, memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
@ -241,8 +280,8 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
static const VMStateDescription vmstate_aspeed_sdmc = { static const VMStateDescription vmstate_aspeed_sdmc = {
.name = "aspeed.sdmc", .name = "aspeed.sdmc",
.version_id = 1, .version_id = 2,
.minimum_version_id = 1, .minimum_version_id = 2,
.fields = (const VMStateField[]) { .fields = (const VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, AspeedSDMCState, ASPEED_SDMC_NR_REGS), VMSTATE_UINT32_ARRAY(regs, AspeedSDMCState, ASPEED_SDMC_NR_REGS),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -251,6 +290,7 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
static Property aspeed_sdmc_properties[] = { static Property aspeed_sdmc_properties[] = {
DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0), DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0),
DEFINE_PROP_BOOL("unlocked", AspeedSDMCState, unlocked, false),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };
@ -311,7 +351,8 @@ static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data) uint32_t data)
{ {
if (reg == R_PROT) { 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; return;
} }
@ -369,7 +410,8 @@ static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data) uint32_t data)
{ {
if (reg == R_PROT) { 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; return;
} }
@ -449,8 +491,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
} }
if (s->regs[R_PROT] == PROT_HARDLOCKED) { if (s->regs[R_PROT] == PROT_HARDLOCKED) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n", qemu_log_mask(LOG_GUEST_ERROR,
__func__); "%s: SDMC is locked until system reset!\n",
__func__);
return; return;
} }
@ -512,12 +555,145 @@ static const TypeInfo aspeed_2600_sdmc_info = {
.class_init = aspeed_2600_sdmc_class_init, .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);
if (s->unlocked) {
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) static void aspeed_sdmc_register_types(void)
{ {
type_register_static(&aspeed_sdmc_info); type_register_static(&aspeed_sdmc_info);
type_register_static(&aspeed_2400_sdmc_info); type_register_static(&aspeed_2400_sdmc_info);
type_register_static(&aspeed_2500_sdmc_info); type_register_static(&aspeed_2500_sdmc_info);
type_register_static(&aspeed_2600_sdmc_info); type_register_static(&aspeed_2600_sdmc_info);
type_register_static(&aspeed_2700_sdmc_info);
} }
type_init(aspeed_sdmc_register_types); type_init(aspeed_sdmc_register_types);

177
hw/misc/aspeed_sli.c Normal file
View File

@ -0,0 +1,177 @@
/*
* ASPEED SLI Controller
*
* Copyright (C) 2024 ASPEED Technology Inc.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#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,
.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);

View File

@ -136,7 +136,8 @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_sbc.c', 'aspeed_sbc.c',
'aspeed_sdmc.c', 'aspeed_sdmc.c',
'aspeed_xdma.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_MSF2', if_true: files('msf2-sysreg.c'))
system_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c')) system_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c'))

View File

@ -93,6 +93,10 @@ slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED 0x%04x"
# aspeed_scu.c # aspeed_scu.c
aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32 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_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.c
mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
@ -351,3 +355,10 @@ djmemc_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRI
# iosb.c # iosb.c
iosb_read(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u" 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" 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

View File

@ -132,6 +132,9 @@
#define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */ #define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */
#define FMC_WDT2_CTRL_EN BIT(0) #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 */ /* DMA Control/Status Register */
#define R_DMA_CTRL (0x80 / 4) #define R_DMA_CTRL (0x80 / 4)
#define DMA_CTRL_REQUEST (1 << 31) #define DMA_CTRL_REQUEST (1 << 31)
@ -178,13 +181,18 @@
* DMA flash addresses should be 4 bytes aligned and the valid address * DMA flash addresses should be 4 bytes aligned and the valid address
* range is 0x20000000 - 0x2FFFFFFF. * range is 0x20000000 - 0x2FFFFFFF.
* *
* DMA length is from 4 bytes to 32MB * DMA length is from 4 bytes to 32MB (AST2500)
* 0: 4 bytes * 0: 4 bytes
* 0x7FFFFF: 32M bytes * 0x1FFFFFC: 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(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_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask)
#define DMA_LENGTH(val) ((val) & 0x01FFFFFC) #define DMA_LENGTH(val) ((val) & 0x01FFFFFF)
/* Flash opcodes. */ /* Flash opcodes. */
#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */ #define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
@ -203,6 +211,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
#define ASPEED_SMC_FEATURE_DMA 0x1 #define ASPEED_SMC_FEATURE_DMA 0x1
#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2 #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
#define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4 #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) static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
{ {
@ -214,6 +223,11 @@ static inline bool aspeed_smc_has_wdt_control(const AspeedSMCClass *asc)
return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL); return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
} }
static inline bool aspeed_smc_has_dma64(const AspeedSMCClass *asc)
{
return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
}
#define aspeed_smc_error(fmt, ...) \ #define aspeed_smc_error(fmt, ...) \
qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__) qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
@ -743,6 +757,8 @@ 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_CTRL) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) || (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) && addr == R_DMA_DRAM_ADDR) ||
(aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) &&
addr == R_DMA_DRAM_ADDR_HIGH) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) || (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
(aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) || (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
(addr >= R_SEG_ADDR0 && (addr >= R_SEG_ADDR0 &&
@ -843,6 +859,19 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
} }
} }
static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s)
{
return s->regs[R_DMA_DRAM_ADDR] |
((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32);
}
static uint32_t aspeed_smc_dma_len(AspeedSMCState *s)
{
AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
return QEMU_ALIGN_UP(s->regs[R_DMA_LEN] + asc->dma_start_length, 4);
}
/* /*
* Accumulate the result of the reads to provide a checksum that will * Accumulate the result of the reads to provide a checksum that will
* be used to validate the read timing settings. * be used to validate the read timing settings.
@ -850,6 +879,7 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
static void aspeed_smc_dma_checksum(AspeedSMCState *s) static void aspeed_smc_dma_checksum(AspeedSMCState *s)
{ {
MemTxResult result; MemTxResult result;
uint32_t dma_len;
uint32_t data; uint32_t data;
if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
@ -861,7 +891,9 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
aspeed_smc_dma_calibration(s); aspeed_smc_dma_calibration(s);
} }
while (s->regs[R_DMA_LEN]) { dma_len = aspeed_smc_dma_len(s);
while (dma_len) {
data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR], data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
MEMTXATTRS_UNSPECIFIED, &result); MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) { if (result != MEMTX_OK) {
@ -877,7 +909,8 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
*/ */
s->regs[R_DMA_CHECKSUM] += data; s->regs[R_DMA_CHECKSUM] += data;
s->regs[R_DMA_FLASH_ADDR] += 4; 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)) { if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
@ -888,21 +921,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
static void aspeed_smc_dma_rw(AspeedSMCState *s) static void aspeed_smc_dma_rw(AspeedSMCState *s)
{ {
AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
uint64_t dma_dram_offset;
uint64_t dma_dram_addr;
MemTxResult result; MemTxResult result;
uint32_t dma_len;
uint32_t data; uint32_t data;
dma_len = aspeed_smc_dma_len(s);
dma_dram_addr = aspeed_smc_dma_dram_addr(s);
if (aspeed_smc_has_dma64(asc)) {
dma_dram_offset = dma_dram_addr - s->dram_base;
} else {
dma_dram_offset = dma_dram_addr;
}
trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ? trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
"write" : "read", "write" : "read",
s->regs[R_DMA_FLASH_ADDR], s->regs[R_DMA_FLASH_ADDR],
s->regs[R_DMA_DRAM_ADDR], dma_dram_offset,
s->regs[R_DMA_LEN]); dma_len);
while (s->regs[R_DMA_LEN]) { while (dma_len) {
if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { 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, dma_dram_offset,
MEMTXATTRS_UNSPECIFIED, &result); MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) { if (result != MEMTX_OK) {
aspeed_smc_error("DRAM read failed @%08x", aspeed_smc_error("DRAM read failed @%" PRIx64,
s->regs[R_DMA_DRAM_ADDR]); dma_dram_offset);
return; return;
} }
@ -922,11 +968,11 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
return; return;
} }
address_space_stl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR], address_space_stl_le(&s->dram_as, dma_dram_offset,
data, MEMTXATTRS_UNSPECIFIED, &result); data, MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) { if (result != MEMTX_OK) {
aspeed_smc_error("DRAM write failed @%08x", aspeed_smc_error("DRAM write failed @%" PRIx64,
s->regs[R_DMA_DRAM_ADDR]); dma_dram_offset);
return; return;
} }
} }
@ -935,9 +981,14 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
* When the DMA is on-going, the DMA registers are updated * When the DMA is on-going, the DMA registers are updated
* with the current working addresses and length. * with the current working addresses and length.
*/ */
dma_dram_offset += 4;
dma_dram_addr += 4;
s->regs[R_DMA_DRAM_ADDR_HIGH] = dma_dram_addr >> 32;
s->regs[R_DMA_DRAM_ADDR] = dma_dram_addr & 0xffffffff;
s->regs[R_DMA_FLASH_ADDR] += 4; s->regs[R_DMA_FLASH_ADDR] += 4;
s->regs[R_DMA_DRAM_ADDR] += 4; dma_len -= 4;
s->regs[R_DMA_LEN] -= 4; s->regs[R_DMA_LEN] = dma_len;
s->regs[R_DMA_CHECKSUM] += data; s->regs[R_DMA_CHECKSUM] += data;
} }
} }
@ -1088,6 +1139,9 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
} else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN && } else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN &&
aspeed_smc_dma_granted(s)) { aspeed_smc_dma_granted(s)) {
s->regs[addr] = DMA_LENGTH(value); s->regs[addr] = DMA_LENGTH(value);
} else if (aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) &&
addr == R_DMA_DRAM_ADDR_HIGH) {
s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
} else { } else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr); __func__, addr);
@ -1220,6 +1274,7 @@ static const VMStateDescription vmstate_aspeed_smc = {
static Property aspeed_smc_properties[] = { static Property aspeed_smc_properties[] = {
DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false), DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false),
DEFINE_PROP_UINT64("dram-base", AspeedSMCState, dram_base, 0),
DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr, DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr,
TYPE_MEMORY_REGION, MemoryRegion *), TYPE_MEMORY_REGION, MemoryRegion *),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
@ -1261,7 +1316,7 @@ static void aspeed_smc_flash_realize(DeviceState *dev, Error **errp)
* Use the default segment value to size the memory region. This * Use the default segment value to size the memory region. This
* can be changed by FW at runtime. * can be changed by FW at runtime.
*/ */
memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_flash_ops, memory_region_init_io(&s->mmio, OBJECT(s), s->asc->reg_ops,
s, name, s->asc->segments[s->cs].size); s, name, s->asc->segments[s->cs].size);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
} }
@ -1336,6 +1391,7 @@ static void aspeed_2400_smc_class_init(ObjectClass *klass, void *data)
asc->segment_to_reg = aspeed_smc_segment_to_reg; asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment; asc->reg_to_segment = aspeed_smc_reg_to_segment;
asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->dma_ctrl = aspeed_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2400_smc_info = { static const TypeInfo aspeed_2400_smc_info = {
@ -1381,10 +1437,12 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA; asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x1FFFFFFC; asc->dma_dram_mask = 0x1FFFFFFC;
asc->dma_start_length = 4;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_smc_segment_to_reg; asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment; asc->reg_to_segment = aspeed_smc_reg_to_segment;
asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->dma_ctrl = aspeed_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2400_fmc_info = { static const TypeInfo aspeed_2400_fmc_info = {
@ -1424,6 +1482,7 @@ static void aspeed_2400_spi1_class_init(ObjectClass *klass, void *data)
asc->reg_to_segment = aspeed_smc_reg_to_segment; asc->reg_to_segment = aspeed_smc_reg_to_segment;
asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->dma_ctrl = aspeed_smc_dma_ctrl;
asc->addr_width = aspeed_2400_spi1_addr_width; asc->addr_width = aspeed_2400_spi1_addr_width;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2400_spi1_info = { static const TypeInfo aspeed_2400_spi1_info = {
@ -1448,7 +1507,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSMCClass *asc = ASPEED_SMC_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_conf = R_CONF;
asc->r_ce_ctrl = R_CE_CTRL; asc->r_ce_ctrl = R_CE_CTRL;
asc->r_ctrl0 = R_CTRL0; asc->r_ctrl0 = R_CTRL0;
@ -1464,10 +1523,12 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA; asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC; asc->dma_dram_mask = 0x3FFFFFFC;
asc->dma_start_length = 4;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_smc_segment_to_reg; asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment; asc->reg_to_segment = aspeed_smc_reg_to_segment;
asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->dma_ctrl = aspeed_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2500_fmc_info = { static const TypeInfo aspeed_2500_fmc_info = {
@ -1486,7 +1547,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSMCClass *asc = ASPEED_SMC_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_conf = R_CONF;
asc->r_ce_ctrl = R_CE_CTRL; asc->r_ce_ctrl = R_CE_CTRL;
asc->r_ctrl0 = R_CTRL0; asc->r_ctrl0 = R_CTRL0;
@ -1503,6 +1564,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass *klass, void *data)
asc->segment_to_reg = aspeed_smc_segment_to_reg; asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment; asc->reg_to_segment = aspeed_smc_reg_to_segment;
asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->dma_ctrl = aspeed_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2500_spi1_info = { static const TypeInfo aspeed_2500_spi1_info = {
@ -1521,7 +1583,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSMCClass *asc = ASPEED_SMC_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_conf = R_CONF;
asc->r_ce_ctrl = R_CE_CTRL; asc->r_ce_ctrl = R_CE_CTRL;
asc->r_ctrl0 = R_CTRL0; asc->r_ctrl0 = R_CTRL0;
@ -1538,6 +1600,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass *klass, void *data)
asc->segment_to_reg = aspeed_smc_segment_to_reg; asc->segment_to_reg = aspeed_smc_segment_to_reg;
asc->reg_to_segment = aspeed_smc_reg_to_segment; asc->reg_to_segment = aspeed_smc_reg_to_segment;
asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->dma_ctrl = aspeed_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2500_spi2_info = { static const TypeInfo aspeed_2500_spi2_info = {
@ -1620,10 +1683,12 @@ static void aspeed_2600_fmc_class_init(ObjectClass *klass, void *data)
ASPEED_SMC_FEATURE_WDT_CONTROL; ASPEED_SMC_FEATURE_WDT_CONTROL;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC; asc->dma_dram_mask = 0x3FFFFFFC;
asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg; asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment; asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2600_fmc_info = { static const TypeInfo aspeed_2600_fmc_info = {
@ -1658,10 +1723,12 @@ static void aspeed_2600_spi1_class_init(ObjectClass *klass, void *data)
ASPEED_SMC_FEATURE_DMA_GRANT; ASPEED_SMC_FEATURE_DMA_GRANT;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC; asc->dma_dram_mask = 0x3FFFFFFC;
asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg; asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment; asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2600_spi1_info = { static const TypeInfo aspeed_2600_spi1_info = {
@ -1697,10 +1764,12 @@ static void aspeed_2600_spi2_class_init(ObjectClass *klass, void *data)
ASPEED_SMC_FEATURE_DMA_GRANT; ASPEED_SMC_FEATURE_DMA_GRANT;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x3FFFFFFC; asc->dma_dram_mask = 0x3FFFFFFC;
asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg; asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment; asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_2600_spi2_info = { static const TypeInfo aspeed_2600_spi2_info = {
@ -1778,10 +1847,12 @@ static void aspeed_1030_fmc_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA; asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x000BFFFC; asc->dma_dram_mask = 0x000BFFFC;
asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_1030_smc_segment_to_reg; asc->segment_to_reg = aspeed_1030_smc_segment_to_reg;
asc->reg_to_segment = aspeed_1030_smc_reg_to_segment; asc->reg_to_segment = aspeed_1030_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_1030_fmc_info = { static const TypeInfo aspeed_1030_fmc_info = {
@ -1815,10 +1886,12 @@ static void aspeed_1030_spi1_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA; asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x000BFFFC; asc->dma_dram_mask = 0x000BFFFC;
asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg; asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment; asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_1030_spi1_info = { static const TypeInfo aspeed_1030_spi1_info = {
@ -1851,10 +1924,12 @@ static void aspeed_1030_spi2_class_init(ObjectClass *klass, void *data)
asc->features = ASPEED_SMC_FEATURE_DMA; asc->features = ASPEED_SMC_FEATURE_DMA;
asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0x000BFFFC; asc->dma_dram_mask = 0x000BFFFC;
asc->dma_start_length = 1;
asc->nregs = ASPEED_SMC_R_MAX; asc->nregs = ASPEED_SMC_R_MAX;
asc->segment_to_reg = aspeed_2600_smc_segment_to_reg; asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2600_smc_reg_to_segment; asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
asc->reg_ops = &aspeed_smc_flash_ops;
} }
static const TypeInfo aspeed_1030_spi2_info = { static const TypeInfo aspeed_1030_spi2_info = {
@ -1863,6 +1938,234 @@ static const TypeInfo aspeed_1030_spi2_info = {
.class_init = aspeed_1030_spi2_class_init, .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 MemoryRegionOps aspeed_2700_smc_flash_ops = {
.read = aspeed_smc_flash_read,
.write = aspeed_smc_flash_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 8,
},
};
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;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
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;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
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;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
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;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
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) static void aspeed_smc_register_types(void)
{ {
type_register_static(&aspeed_smc_flash_info); type_register_static(&aspeed_smc_flash_info);
@ -1879,6 +2182,10 @@ static void aspeed_smc_register_types(void)
type_register_static(&aspeed_1030_fmc_info); type_register_static(&aspeed_1030_fmc_info);
type_register_static(&aspeed_1030_spi1_info); type_register_static(&aspeed_1030_spi1_info);
type_register_static(&aspeed_1030_spi2_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) type_init(aspeed_smc_register_types)

View File

@ -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_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_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_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_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" aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"

View File

@ -422,12 +422,36 @@ static const TypeInfo aspeed_1030_wdt_info = {
.class_init = aspeed_1030_wdt_class_init, .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) static void wdt_aspeed_register_types(void)
{ {
type_register_static(&aspeed_wdt_info); type_register_static(&aspeed_wdt_info);
type_register_static(&aspeed_2400_wdt_info); type_register_static(&aspeed_2400_wdt_info);
type_register_static(&aspeed_2500_wdt_info); type_register_static(&aspeed_2500_wdt_info);
type_register_static(&aspeed_2600_wdt_info); type_register_static(&aspeed_2600_wdt_info);
type_register_static(&aspeed_2700_wdt_info);
type_register_static(&aspeed_1030_wdt_info); type_register_static(&aspeed_1030_wdt_info);
} }

View File

@ -15,6 +15,7 @@
#include "hw/cpu/a15mpcore.h" #include "hw/cpu/a15mpcore.h"
#include "hw/arm/armv7m.h" #include "hw/arm/armv7m.h"
#include "hw/intc/aspeed_vic.h" #include "hw/intc/aspeed_vic.h"
#include "hw/intc/aspeed_intc.h"
#include "hw/misc/aspeed_scu.h" #include "hw/misc/aspeed_scu.h"
#include "hw/adc/aspeed_adc.h" #include "hw/adc/aspeed_adc.h"
#include "hw/misc/aspeed_sdmc.h" #include "hw/misc/aspeed_sdmc.h"
@ -26,6 +27,7 @@
#include "hw/ssi/aspeed_smc.h" #include "hw/ssi/aspeed_smc.h"
#include "hw/misc/aspeed_hace.h" #include "hw/misc/aspeed_hace.h"
#include "hw/misc/aspeed_sbc.h" #include "hw/misc/aspeed_sbc.h"
#include "hw/misc/aspeed_sli.h"
#include "hw/watchdog/wdt_aspeed.h" #include "hw/watchdog/wdt_aspeed.h"
#include "hw/net/ftgmac100.h" #include "hw/net/ftgmac100.h"
#include "target/arm/cpu.h" #include "target/arm/cpu.h"
@ -38,11 +40,12 @@
#include "hw/misc/aspeed_peci.h" #include "hw/misc/aspeed_peci.h"
#include "hw/fsi/aspeed_apb2opb.h" #include "hw/fsi/aspeed_apb2opb.h"
#include "hw/char/serial.h" #include "hw/char/serial.h"
#include "hw/intc/arm_gicv3.h"
#define ASPEED_SPIS_NUM 2 #define ASPEED_SPIS_NUM 2
#define ASPEED_EHCIS_NUM 2 #define ASPEED_EHCIS_NUM 2
#define ASPEED_WDTS_NUM 4 #define ASPEED_WDTS_NUM 8
#define ASPEED_CPUS_NUM 2 #define ASPEED_CPUS_NUM 4
#define ASPEED_MACS_NUM 4 #define ASPEED_MACS_NUM 4
#define ASPEED_UARTS_NUM 13 #define ASPEED_UARTS_NUM 13
#define ASPEED_JTAG_NUM 2 #define ASPEED_JTAG_NUM 2
@ -56,11 +59,13 @@ struct AspeedSoCState {
MemoryRegion sram; MemoryRegion sram;
MemoryRegion spi_boot_container; MemoryRegion spi_boot_container;
MemoryRegion spi_boot; MemoryRegion spi_boot;
AddressSpace dram_as;
AspeedRtcState rtc; AspeedRtcState rtc;
AspeedTimerCtrlState timerctrl; AspeedTimerCtrlState timerctrl;
AspeedI2CState i2c; AspeedI2CState i2c;
AspeedI3CState i3c; AspeedI3CState i3c;
AspeedSCUState scu; AspeedSCUState scu;
AspeedSCUState scuio;
AspeedHACEState hace; AspeedHACEState hace;
AspeedXDMAState xdma; AspeedXDMAState xdma;
AspeedADCState adc; AspeedADCState adc;
@ -68,6 +73,8 @@ struct AspeedSoCState {
AspeedSMCState spi[ASPEED_SPIS_NUM]; AspeedSMCState spi[ASPEED_SPIS_NUM];
EHCISysBusState ehci[ASPEED_EHCIS_NUM]; EHCISysBusState ehci[ASPEED_EHCIS_NUM];
AspeedSBCState sbc; AspeedSBCState sbc;
AspeedSLIState sli;
AspeedSLIState sliio;
MemoryRegion secsram; MemoryRegion secsram;
UnimplementedDeviceState sbc_unimplemented; UnimplementedDeviceState sbc_unimplemented;
AspeedSDMCState sdmc; AspeedSDMCState sdmc;
@ -117,6 +124,18 @@ struct Aspeed2600SoCState {
#define TYPE_ASPEED2600_SOC "aspeed2600-soc" #define TYPE_ASPEED2600_SOC "aspeed2600-soc"
OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2600SoCState, ASPEED2600_SOC) OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2600SoCState, ASPEED2600_SOC)
struct Aspeed27x0SoCState {
AspeedSoCState parent;
ARMCPU cpu[ASPEED_CPUS_NUM];
AspeedINTCState intc;
GICv3State gic;
MemoryRegion dram_empty;
};
#define TYPE_ASPEED27X0_SOC "aspeed27x0-soc"
OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0SoCState, ASPEED27X0_SOC)
struct Aspeed10x0SoCState { struct Aspeed10x0SoCState {
AspeedSoCState parent; AspeedSoCState parent;
@ -168,11 +187,13 @@ enum {
ASPEED_DEV_UART13, ASPEED_DEV_UART13,
ASPEED_DEV_VUART, ASPEED_DEV_VUART,
ASPEED_DEV_FMC, ASPEED_DEV_FMC,
ASPEED_DEV_SPI0,
ASPEED_DEV_SPI1, ASPEED_DEV_SPI1,
ASPEED_DEV_SPI2, ASPEED_DEV_SPI2,
ASPEED_DEV_EHCI1, ASPEED_DEV_EHCI1,
ASPEED_DEV_EHCI2, ASPEED_DEV_EHCI2,
ASPEED_DEV_VIC, ASPEED_DEV_VIC,
ASPEED_DEV_INTC,
ASPEED_DEV_SDMC, ASPEED_DEV_SDMC,
ASPEED_DEV_SCU, ASPEED_DEV_SCU,
ASPEED_DEV_ADC, ASPEED_DEV_ADC,
@ -222,6 +243,11 @@ enum {
ASPEED_DEV_JTAG1, ASPEED_DEV_JTAG1,
ASPEED_DEV_FSI1, ASPEED_DEV_FSI1,
ASPEED_DEV_FSI2, 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); qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);

View File

@ -0,0 +1,44 @@
/*
* ASPEED INTC Controller
*
* Copyright (C) 2024 ASPEED Technology Inc.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ASPEED_INTC_H
#define ASPEED_INTC_H
#include "hw/sysbus.h"
#include "qom/object.h"
#include "hw/or-irq.h"
#define TYPE_ASPEED_INTC "aspeed.intc"
#define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
#define ASPEED_INTC_NR_INTS 9
struct AspeedINTCState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
uint32_t regs[ASPEED_INTC_NR_REGS];
OrIRQState orgates[ASPEED_INTC_NR_INTS];
qemu_irq output_pins[ASPEED_INTC_NR_INTS];
uint32_t enable[ASPEED_INTC_NR_INTS];
uint32_t mask[ASPEED_INTC_NR_INTS];
uint32_t pending[ASPEED_INTC_NR_INTS];
};
struct AspeedINTCClass {
SysBusDeviceClass parent_class;
uint32_t num_lines;
uint32_t num_ints;
};
#endif /* ASPEED_INTC_H */

View File

@ -19,10 +19,13 @@ OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEED_SCU)
#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400" #define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500" #define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
#define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600" #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 TYPE_ASPEED_1030_SCU TYPE_ASPEED_SCU "-ast1030"
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2) #define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
#define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2) #define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
#define ASPEED_AST2700_SCU_NR_REGS (0xE20 >> 2)
struct AspeedSCUState { struct AspeedSCUState {
/*< private >*/ /*< private >*/
@ -31,7 +34,7 @@ struct AspeedSCUState {
/*< public >*/ /*< public >*/
MemoryRegion iomem; MemoryRegion iomem;
uint32_t regs[ASPEED_AST2600_SCU_NR_REGS]; uint32_t regs[ASPEED_AST2700_SCU_NR_REGS];
uint32_t silicon_rev; uint32_t silicon_rev;
uint32_t hw_strap1; uint32_t hw_strap1;
uint32_t hw_strap2; uint32_t hw_strap2;
@ -48,6 +51,9 @@ struct AspeedSCUState {
#define AST2600_A3_SILICON_REV 0x05030303U #define AST2600_A3_SILICON_REV 0x05030303U
#define AST1030_A0_SILICON_REV 0x80000000U #define AST1030_A0_SILICON_REV 0x80000000U
#define AST1030_A1_SILICON_REV 0x80010000U #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) #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 * 1. 2012/12/29 Ryan Chen Create
*/ */
/* SCU08 Clock Selection Register /*
* SCU08 Clock Selection Register
* *
* 31 Enable Video Engine clock dynamic slow down * 31 Enable Video Engine clock dynamic slow down
* 30:28 Video Engine clock slow down setting * 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) #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 * 18 H-PLL parameter selection
* 0: Select H-PLL by strapping resistors * 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_BYPASS_EN (0x1 << 17)
#define SCU_AST2400_H_PLL_OFF (0x1 << 16) #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 * 21 Enable H-PLL reset
* 20 Enable H-PLL bypass mode * 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_BYPASS_EN (0x1 << 20)
#define SCU_H_PLL_OFF (0x1 << 19) #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 * 31:29 Software defined strapping registers
* 28:27 DRAM size setting (for VGA driver use) * 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) #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 */ #endif /* ASPEED_SCU_H */

View File

@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
#define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400" #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
#define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500" #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
#define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600" #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 * 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 * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
* training. * training.
*/ */
#define ASPEED_SDMC_NR_REGS (0x500 >> 2) #define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
struct AspeedSDMCState { struct AspeedSDMCState {
/*< private >*/ /*< private >*/
@ -41,6 +42,7 @@ struct AspeedSDMCState {
uint32_t regs[ASPEED_SDMC_NR_REGS]; uint32_t regs[ASPEED_SDMC_NR_REGS];
uint64_t ram_size; uint64_t ram_size;
uint64_t max_ram_size; uint64_t max_ram_size;
bool unlocked;
}; };
@ -51,6 +53,7 @@ struct AspeedSDMCClass {
const uint64_t *valid_ram_sizes; const uint64_t *valid_ram_sizes;
uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data); uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data); void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
bool is_bus64bit;
}; };
#endif /* ASPEED_SDMC_H */ #endif /* ASPEED_SDMC_H */

View File

@ -0,0 +1,27 @@
/*
* ASPEED SLI Controller
*
* Copyright (C) 2024 ASPEED Technology Inc.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#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_SIMPLE_TYPE(AspeedSLIState, ASPEED_SLI)
#define ASPEED_SLI_NR_REGS (0x500 >> 2)
struct AspeedSLIState {
SysBusDevice parent;
MemoryRegion iomem;
uint32_t regs[ASPEED_SLI_NR_REGS];
};
#endif /* ASPEED_SLI_H */

View File

@ -76,6 +76,7 @@ struct AspeedSMCState {
AddressSpace flash_as; AddressSpace flash_as;
MemoryRegion *dram_mr; MemoryRegion *dram_mr;
AddressSpace dram_as; AddressSpace dram_as;
uint64_t dram_base;
AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX]; AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX];
@ -106,6 +107,7 @@ struct AspeedSMCClass {
uint32_t features; uint32_t features;
hwaddr dma_flash_mask; hwaddr dma_flash_mask;
hwaddr dma_dram_mask; hwaddr dma_dram_mask;
uint32_t dma_start_length;
uint32_t nregs; uint32_t nregs;
uint32_t (*segment_to_reg)(const AspeedSMCState *s, uint32_t (*segment_to_reg)(const AspeedSMCState *s,
const AspeedSegments *seg); const AspeedSegments *seg);
@ -113,6 +115,7 @@ struct AspeedSMCClass {
AspeedSegments *seg); AspeedSegments *seg);
void (*dma_ctrl)(AspeedSMCState *s, uint32_t value); void (*dma_ctrl)(AspeedSMCState *s, uint32_t value);
int (*addr_width)(const AspeedSMCState *s); int (*addr_width)(const AspeedSMCState *s);
const MemoryRegionOps *reg_ops;
}; };
#endif /* ASPEED_SMC_H */ #endif /* ASPEED_SMC_H */

View File

@ -19,9 +19,10 @@ OBJECT_DECLARE_TYPE(AspeedWDTState, AspeedWDTClass, ASPEED_WDT)
#define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400" #define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
#define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500" #define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
#define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600" #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 TYPE_ASPEED_1030_WDT TYPE_ASPEED_WDT "-ast1030"
#define ASPEED_WDT_REGS_MAX (0x30 / 4) #define ASPEED_WDT_REGS_MAX (0x80 / 4)
struct AspeedWDTState { struct AspeedWDTState {
/*< private >*/ /*< private >*/

View File

@ -311,6 +311,17 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
self, 'boot', '## Loading kernel from FIT Image') self, 'boot', '## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...') self.wait_for_console_pattern('Starting kernel ...')
def do_test_aarch64_aspeed_sdk_start(self, image):
self.vm.set_console()
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw')
self.vm.launch()
self.wait_for_console_pattern('U-Boot 2023.10')
self.wait_for_console_pattern('## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...')
self.wait_for_console_pattern("systemd[1]: Hostname set to")
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_arm_ast2500_evb_sdk(self): def test_arm_ast2500_evb_sdk(self):
@ -375,3 +386,54 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32'); 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32');
year = time.strftime("%Y") year = time.strftime("%Y")
self.ssh_command_output_contains('/sbin/hwclock -f /dev/rtc1', year); self.ssh_command_output_contains('/sbin/hwclock -f /dev/rtc1', year);
def test_aarch64_ast2700_evb_sdk_v09_01(self):
"""
:avocado: tags=arch:aarch64
:avocado: tags=machine:ast2700-evb
"""
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
'download/v09.01/ast2700-default-obmc.tar.gz')
image_hash = 'b1cc0fd73c7650d34c9c8459a243f52a91e9e27144b8608b2645ab19461d1e07'
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
algorithm='sha256')
archive.extract(image_path, self.workdir)
num_cpu = 4
image_dir = self.workdir + '/ast2700-default/'
uboot_size = os.path.getsize(image_dir + 'u-boot-nodtb.bin')
uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
load_images_list = [
{
'addr': '0x400000000',
'file': image_dir + 'u-boot-nodtb.bin'
},
{
'addr': str(uboot_dtb_load_addr),
'file': image_dir + 'u-boot.dtb'
},
{
'addr': '0x430000000',
'file': image_dir + 'bl31.bin'
},
{
'addr': '0x430080000',
'file': image_dir + 'optee/tee-raw.bin'
}
]
for load_image in load_images_list:
addr = load_image['addr']
file = load_image['file']
self.vm.add_args('-device',
f'loader,force-raw=on,addr={addr},file={file}')
for i in range(num_cpu):
self.vm.add_args('-device',
f'loader,addr=0x430000000,cpu-num={i}')
self.vm.add_args('-smp', str(num_cpu))
self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')