aspeed queue:

* Fixed serial definitions on the command line
 * Fixed sdhci write protected pin on AST2600 EVB machine
 * Added timer support on AST2700 SoC
 * Updated buildroot and SDK images of functional tests
 * Removed sd devices creation when -nodefaults is used
 * Added software reset mode support on AST2600 SoC
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmeXSIwACgkQUaNDx8/7
 7KH5Ew/+Ne9Z0lksOEUw5BJ6Qm3U2oLS90hcjo3MBHpmMHX0MXY2qYOKV2aS7spO
 kvWpTUiPaT682X4IrBuxdCdi2F80dhJSmky81vMn7a3+DZgSsUoPEgw2Ophm5Q37
 788qVEKk55F8m4r4ZCpAd3+Mc+3rVw6YQW/Rvu2+fVbfaLu6dE4fnQdXmDYc2EzF
 pCYAcYlRp19dP0YnBJnv4/JK6Eybced1VG1cKGNy8VSyMY3vWM7ZOdP4Ybz+d88R
 0DNEIGRQJQZZFNxvkEJX/tPsK+m2M9G/t5YOuJP22EoF3L8v+rnt7yg+NWE4pbtI
 dqzg8ikICidcP6NMYjTe6C2m9PBcKBhbPumRZOW1lWRoZOShy6cHO7KajJZ3oj8K
 GUOEEh7i5tKbPGdg46ifc0waGMKh97S3dy/8V/N2XqPfL99TXfRAyiq0sG0mS1je
 xGV9vN7LPJ9OYMri6U5SLewrWO93q7Vv4SBv7iDVupZ8Ww6wcJaCWgvUWjxbK7SH
 qE003RvQYmK6gkCH4cYnI2LZBlJyp7wKdO7nG4K2vI+05GVpALTkZPcCQ84WhF5L
 8wO5wrQPalQrOwkvankqgEJOifWmBAi3Gs/3y/tRg+u4VHoPKcaXLujBqq8pZl6F
 meYAzqqksFj8PJwiCVJVNcHpqvhmyBzvvPAf6NEgbRsDyUiFZAo=
 =gOq1
 -----END PGP SIGNATURE-----

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

aspeed queue:

* Fixed serial definitions on the command line
* Fixed sdhci write protected pin on AST2600 EVB machine
* Added timer support on AST2700 SoC
* Updated buildroot and SDK images of functional tests
* Removed sd devices creation when -nodefaults is used
* Added software reset mode support on AST2600 SoC

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmeXSIwACgkQUaNDx8/7
# 7KH5Ew/+Ne9Z0lksOEUw5BJ6Qm3U2oLS90hcjo3MBHpmMHX0MXY2qYOKV2aS7spO
# kvWpTUiPaT682X4IrBuxdCdi2F80dhJSmky81vMn7a3+DZgSsUoPEgw2Ophm5Q37
# 788qVEKk55F8m4r4ZCpAd3+Mc+3rVw6YQW/Rvu2+fVbfaLu6dE4fnQdXmDYc2EzF
# pCYAcYlRp19dP0YnBJnv4/JK6Eybced1VG1cKGNy8VSyMY3vWM7ZOdP4Ybz+d88R
# 0DNEIGRQJQZZFNxvkEJX/tPsK+m2M9G/t5YOuJP22EoF3L8v+rnt7yg+NWE4pbtI
# dqzg8ikICidcP6NMYjTe6C2m9PBcKBhbPumRZOW1lWRoZOShy6cHO7KajJZ3oj8K
# GUOEEh7i5tKbPGdg46ifc0waGMKh97S3dy/8V/N2XqPfL99TXfRAyiq0sG0mS1je
# xGV9vN7LPJ9OYMri6U5SLewrWO93q7Vv4SBv7iDVupZ8Ww6wcJaCWgvUWjxbK7SH
# qE003RvQYmK6gkCH4cYnI2LZBlJyp7wKdO7nG4K2vI+05GVpALTkZPcCQ84WhF5L
# 8wO5wrQPalQrOwkvankqgEJOifWmBAi3Gs/3y/tRg+u4VHoPKcaXLujBqq8pZl6F
# meYAzqqksFj8PJwiCVJVNcHpqvhmyBzvvPAf6NEgbRsDyUiFZAo=
# =gOq1
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 27 Jan 2025 03:49:16 EST
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full]
# gpg:                 aka "Cédric Le Goater <clg@kaod.org>" [full]
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* tag 'pull-aspeed-20250127' of https://github.com/legoater/qemu:
  docs/system/arm/aspeed: Remove tacoma-bmc from the documentation
  aspeed/wdt: Support software reset mode for AST2600
  aspeed/wdt: Fix coding style
  aspeed: Create sd devices only when defaults are enabled
  test/functional: Update buildroot images to 2024.11
  test/functional: Update the Aspeed aarch64 test
  aspeed/soc: Support Timer for AST2700
  hw/timer/aspeed: Add AST2700 Support
  hw/timer/aspeed: Refactor Timer Callbacks for SoC-Specific Implementations
  hw/arm/aspeed: Invert sdhci write protected pin for AST2600 EVB
  hw/sd/sdhci: Introduce a new Write Protected pin inverted property
  hw/arm/aspeed: fix connect_serial_hds_to_uarts

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-01-27 11:20:35 -05:00
commit 7faf9d2f12
14 changed files with 323 additions and 38 deletions

View File

@ -1,5 +1,5 @@
Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``tacoma-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``)
================================================================================================================================================================================================================================================================================================================================================================================================================================== ==================================================================================================================================================================================================================================================================================================================================================================================================================
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

View File

@ -364,11 +364,11 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc)
int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; uart++) {
if (uart == uart_chosen) { if (uart == uart_chosen) {
continue; continue;
} }
aspeed_soc_uart_set_chr(s, uart, serial_hd(i)); aspeed_soc_uart_set_chr(s, uart, serial_hd(i++));
} }
} }
@ -409,6 +409,12 @@ static void aspeed_machine_init(MachineState *machine)
OBJECT(get_system_memory()), &error_abort); OBJECT(get_system_memory()), &error_abort);
object_property_set_link(OBJECT(bmc->soc), "dram", object_property_set_link(OBJECT(bmc->soc), "dram",
OBJECT(machine->ram), &error_abort); OBJECT(machine->ram), &error_abort);
if (amc->sdhci_wp_inverted) {
for (i = 0; i < bmc->soc->sdhci.num_slots; i++) {
object_property_set_bool(OBJECT(&bmc->soc->sdhci.slots[i]),
"wp-inverted", true, &error_abort);
}
}
if (machine->kernel_filename) { if (machine->kernel_filename) {
/* /*
* When booting with a -kernel command line there is no u-boot * When booting with a -kernel command line there is no u-boot
@ -450,14 +456,14 @@ static void aspeed_machine_init(MachineState *machine)
amc->i2c_init(bmc); amc->i2c_init(bmc);
} }
for (i = 0; i < bmc->soc->sdhci.num_slots; i++) { for (i = 0; i < bmc->soc->sdhci.num_slots && defaults_enabled(); i++) {
sdhci_attach_drive(&bmc->soc->sdhci.slots[i], sdhci_attach_drive(&bmc->soc->sdhci.slots[i],
drive_get(IF_SD, 0, i), false, false); drive_get(IF_SD, 0, i), false, false);
} }
boot_emmc = sc->boot_from_emmc(bmc->soc); boot_emmc = sc->boot_from_emmc(bmc->soc);
if (bmc->soc->emmc.num_slots) { if (bmc->soc->emmc.num_slots && defaults_enabled()) {
emmc0 = drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots); emmc0 = drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots);
sdhci_attach_drive(&bmc->soc->emmc.slots[0], emmc0, true, boot_emmc); sdhci_attach_drive(&bmc->soc->emmc.slots[0], emmc0, true, boot_emmc);
} }
@ -1415,6 +1421,7 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
amc->num_cs = 1; amc->num_cs = 1;
amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON | amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON |
ASPEED_MAC3_ON; ASPEED_MAC3_ON;
amc->sdhci_wp_inverted = true;
amc->i2c_init = ast2600_evb_i2c_init; amc->i2c_init = ast2600_evb_i2c_init;
mc->default_ram_size = 1 * GiB; mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc); aspeed_machine_class_init_cpus_defaults(mc);

View File

@ -66,6 +66,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
[ASPEED_DEV_GPIO] = 0x14C0B000, [ASPEED_DEV_GPIO] = 0x14C0B000,
[ASPEED_DEV_RTC] = 0x12C0F000, [ASPEED_DEV_RTC] = 0x12C0F000,
[ASPEED_DEV_SDHCI] = 0x14080000, [ASPEED_DEV_SDHCI] = 0x14080000,
[ASPEED_DEV_TIMER1] = 0x12C10000,
}; };
#define AST2700_MAX_IRQ 256 #define AST2700_MAX_IRQ 256
@ -397,6 +398,9 @@ static void aspeed_soc_ast2700_init(Object *obj)
object_initialize_child(obj, "emmc-controller.sdhci", &s->emmc.slots[0], object_initialize_child(obj, "emmc-controller.sdhci", &s->emmc.slots[0],
TYPE_SYSBUS_SDHCI); TYPE_SYSBUS_SDHCI);
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
object_initialize_child(obj, "timerctrl", &s->timerctrl, typename);
} }
/* /*
@ -716,6 +720,19 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0, sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_EMMC)); aspeed_soc_get_irq(s, ASPEED_DEV_EMMC));
/* Timer */
object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),
&error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) {
return;
}
aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0,
sc->memmap[ASPEED_DEV_TIMER1]);
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000); create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000);
create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000); create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000);
create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000); create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000);

View File

@ -274,6 +274,10 @@ static void sdhci_set_readonly(DeviceState *dev, bool level)
{ {
SDHCIState *s = (SDHCIState *)dev; SDHCIState *s = (SDHCIState *)dev;
if (s->wp_inverted) {
level = !level;
}
if (level) { if (level) {
s->prnsts &= ~SDHC_WRITE_PROTECT; s->prnsts &= ~SDHC_WRITE_PROTECT;
} else { } else {
@ -1555,6 +1559,8 @@ static const Property sdhci_sysbus_properties[] = {
false), false),
DEFINE_PROP_LINK("dma", SDHCIState, DEFINE_PROP_LINK("dma", SDHCIState,
dma_mr, TYPE_MEMORY_REGION, MemoryRegion *), dma_mr, TYPE_MEMORY_REGION, MemoryRegion *),
DEFINE_PROP_BOOL("wp-inverted", SDHCIState,
wp_inverted, false),
}; };
static void sdhci_sysbus_init(Object *obj) static void sdhci_sysbus_init(Object *obj)

View File

@ -239,9 +239,8 @@ static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
return value; return value;
} }
static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size) static uint64_t aspeed_timer_read_common(AspeedTimerCtrlState *s, hwaddr offset)
{ {
AspeedTimerCtrlState *s = opaque;
const int reg = (offset & 0xf) / 4; const int reg = (offset & 0xf) / 4;
uint64_t value; uint64_t value;
@ -256,10 +255,11 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg); value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
break; break;
default: default:
value = ASPEED_TIMER_GET_CLASS(s)->read(s, offset); qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
value = 0;
break; break;
} }
trace_aspeed_timer_read(offset, size, value);
return value; return value;
} }
@ -431,12 +431,11 @@ static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
trace_aspeed_timer_set_ctrl2(value); trace_aspeed_timer_set_ctrl2(value);
} }
static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value, static void aspeed_timer_write_common(AspeedTimerCtrlState *s, hwaddr offset,
unsigned size) uint64_t value)
{ {
const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF); const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
const int reg = (offset & 0xf) / 4; const int reg = (offset & 0xf) / 4;
AspeedTimerCtrlState *s = opaque;
switch (offset) { switch (offset) {
/* Control Registers */ /* Control Registers */
@ -451,11 +450,25 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv); aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
break; break;
default: default:
ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value); qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
break; break;
} }
} }
static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
{
AspeedTimerCtrlState *s = ASPEED_TIMER(opaque);
return ASPEED_TIMER_GET_CLASS(s)->read(s, offset);
}
static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
AspeedTimerCtrlState *s = ASPEED_TIMER(opaque);
ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value);
}
static const MemoryRegionOps aspeed_timer_ops = { static const MemoryRegionOps aspeed_timer_ops = {
.read = aspeed_timer_read, .read = aspeed_timer_read,
.write = aspeed_timer_write, .write = aspeed_timer_write,
@ -475,12 +488,15 @@ static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
break; break;
case 0x38: case 0x38:
case 0x3C: case 0x3C:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset); __func__, offset);
value = 0; value = 0;
break; break;
default:
value = aspeed_timer_read_common(s, offset);
break;
} }
trace_aspeed_timer_read(offset, value);
return value; return value;
} }
@ -495,10 +511,12 @@ static void aspeed_2400_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
break; break;
case 0x38: case 0x38:
case 0x3C: case 0x3C:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset); __func__, offset);
break; break;
default:
aspeed_timer_write_common(s, offset, value);
break;
} }
} }
@ -514,12 +532,15 @@ static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
value = s->ctrl3 & BIT(0); value = s->ctrl3 & BIT(0);
break; break;
case 0x3C: case 0x3C:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset); __func__, offset);
value = 0; value = 0;
break; break;
default:
value = aspeed_timer_read_common(s, offset);
break;
} }
trace_aspeed_timer_read(offset, value);
return value; return value;
} }
@ -548,8 +569,7 @@ static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
break; break;
default: default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", aspeed_timer_write_common(s, offset, value);
__func__, offset);
break; break;
} }
} }
@ -564,12 +584,15 @@ static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
break; break;
case 0x38: case 0x38:
case 0x3C: case 0x3C:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset); __func__, offset);
value = 0; value = 0;
break; break;
default:
value = aspeed_timer_read_common(s, offset);
break;
} }
trace_aspeed_timer_read(offset, value);
return value; return value;
} }
@ -586,10 +609,203 @@ static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
aspeed_timer_set_ctrl(s, s->ctrl & ~tv); aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
break; break;
case 0x38: case 0x38:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset); __func__, offset);
break; break;
default:
aspeed_timer_write_common(s, offset, value);
break;
}
}
static void aspeed_2700_timer_set_ctrl(AspeedTimerCtrlState *s, int index,
uint32_t reg)
{
const uint8_t overflow_interrupt_mask = BIT(op_overflow_interrupt);
const uint8_t external_clock_mask = BIT(op_external_clock);
const uint8_t pulse_enable_mask = BIT(op_pulse_enable);
const uint8_t enable_mask = BIT(op_enable);
AspeedTimer *t;
uint8_t t_old;
uint8_t t_new;
int shift;
/*
* Only 1 will set the specific bits to 1
* Handle a dependency between the 'enable' and remaining three
* configuration bits - i.e. if more than one bit in the control set has
* set, including the 'enable' bit, perform configuration and then
* enable the timer.
* Interrupt Status bit should not be set.
*/
t = &s->timers[index];
shift = index * TIMER_CTRL_BITS;
t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
t_new = reg & TIMER_CTRL_MASK;
if (!(t_old & external_clock_mask) &&
(t_new & external_clock_mask)) {
aspeed_timer_ctrl_external_clock(t, true);
s->ctrl = deposit32(s->ctrl, shift + op_external_clock, 1, 1);
}
if (!(t_old & overflow_interrupt_mask) &&
(t_new & overflow_interrupt_mask)) {
aspeed_timer_ctrl_overflow_interrupt(t, true);
s->ctrl = deposit32(s->ctrl, shift + op_overflow_interrupt, 1, 1);
}
if (!(t_old & pulse_enable_mask) &&
(t_new & pulse_enable_mask)) {
aspeed_timer_ctrl_pulse_enable(t, true);
s->ctrl = deposit32(s->ctrl, shift + op_pulse_enable, 1, 1);
}
/* If we are enabling, do so last */
if (!(t_old & enable_mask) &&
(t_new & enable_mask)) {
aspeed_timer_ctrl_enable(t, true);
s->ctrl = deposit32(s->ctrl, shift + op_enable, 1, 1);
}
}
static void aspeed_2700_timer_clear_ctrl(AspeedTimerCtrlState *s, int index,
uint32_t reg)
{
const uint8_t overflow_interrupt_mask = BIT(op_overflow_interrupt);
const uint8_t external_clock_mask = BIT(op_external_clock);
const uint8_t pulse_enable_mask = BIT(op_pulse_enable);
const uint8_t enable_mask = BIT(op_enable);
AspeedTimer *t;
uint8_t t_old;
uint8_t t_new;
int shift;
/*
* Only 1 will clear the specific bits to 0
* Handle a dependency between the 'enable' and remaining three
* configuration bits - i.e. if more than one bit in the control set has
* clear, including the 'enable' bit, then disable the timer and perform
* configuration
*/
t = &s->timers[index];
shift = index * TIMER_CTRL_BITS;
t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
t_new = reg & TIMER_CTRL_MASK;
/* If we are disabling, do so first */
if ((t_old & enable_mask) &&
(t_new & enable_mask)) {
aspeed_timer_ctrl_enable(t, false);
s->ctrl = deposit32(s->ctrl, shift + op_enable, 1, 0);
}
if ((t_old & external_clock_mask) &&
(t_new & external_clock_mask)) {
aspeed_timer_ctrl_external_clock(t, false);
s->ctrl = deposit32(s->ctrl, shift + op_external_clock, 1, 0);
}
if ((t_old & overflow_interrupt_mask) &&
(t_new & overflow_interrupt_mask)) {
aspeed_timer_ctrl_overflow_interrupt(t, false);
s->ctrl = deposit32(s->ctrl, shift + op_overflow_interrupt, 1, 0);
}
if ((t_old & pulse_enable_mask) &&
(t_new & pulse_enable_mask)) {
aspeed_timer_ctrl_pulse_enable(t, false);
s->ctrl = deposit32(s->ctrl, shift + op_pulse_enable, 1, 0);
}
/* Clear interrupt status */
if (reg & 0x10000) {
s->irq_sts = deposit32(s->irq_sts, index, 1, 0);
}
}
static uint64_t aspeed_2700_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
{
uint32_t timer_offset = offset & 0x3f;
int timer_index = offset >> 6;
uint64_t value = 0;
if (timer_index >= ASPEED_TIMER_NR_TIMERS) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: offset 0x%" PRIx64 " out of bounds\n",
__func__, offset);
return 0;
}
switch (timer_offset) {
/*
* Counter Status
* Counter Reload
* Counter First Matching
* Counter Second Matching
*/
case 0x00 ... 0x0C:
value = aspeed_timer_get_value(&s->timers[timer_index],
timer_offset >> 2);
break;
/* Counter Control and Interrupt Status */
case 0x10:
value = deposit64(value, 0, 4,
extract32(s->ctrl, timer_index * 4, 4));
value = deposit64(value, 16, 1,
extract32(s->irq_sts, timer_index, 1));
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
PRIx64"\n", __func__, offset);
value = 0;
break;
}
trace_aspeed_timer_read(offset, value);
return value;
}
static void aspeed_2700_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
uint64_t value)
{
const uint32_t timer_value = (uint32_t)(value & 0xFFFFFFFF);
uint32_t timer_offset = offset & 0x3f;
int timer_index = offset >> 6;
if (timer_index >= ASPEED_TIMER_NR_TIMERS) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: offset 0x%" PRIx64 " out of bounds\n",
__func__, offset);
}
switch (timer_offset) {
/*
* Counter Status
* Counter Reload
* Counter First Matching
* Counter Second Matching
*/
case 0x00 ... 0x0C:
aspeed_timer_set_value(s, timer_index, timer_offset >> 2,
timer_value);
break;
/* Counter Control Set and Interrupt Status */
case 0x10:
aspeed_2700_timer_set_ctrl(s, timer_index, timer_value);
break;
/* Counter Control Clear and Interrupr Status */
case 0x14:
aspeed_2700_timer_clear_ctrl(s, timer_index, timer_value);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
PRIx64"\n", __func__, offset);
break;
} }
} }
@ -763,6 +979,22 @@ static const TypeInfo aspeed_1030_timer_info = {
.class_init = aspeed_1030_timer_class_init, .class_init = aspeed_1030_timer_class_init,
}; };
static void aspeed_2700_timer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
dc->desc = "ASPEED 2700 Timer";
awc->read = aspeed_2700_timer_read;
awc->write = aspeed_2700_timer_write;
}
static const TypeInfo aspeed_2700_timer_info = {
.name = TYPE_ASPEED_2700_TIMER,
.parent = TYPE_ASPEED_TIMER,
.class_init = aspeed_2700_timer_class_init,
};
static void aspeed_timer_register_types(void) static void aspeed_timer_register_types(void)
{ {
type_register_static(&aspeed_timer_info); type_register_static(&aspeed_timer_info);
@ -770,6 +1002,7 @@ static void aspeed_timer_register_types(void)
type_register_static(&aspeed_2500_timer_info); type_register_static(&aspeed_2500_timer_info);
type_register_static(&aspeed_2600_timer_info); type_register_static(&aspeed_2600_timer_info);
type_register_static(&aspeed_1030_timer_info); type_register_static(&aspeed_1030_timer_info);
type_register_static(&aspeed_2700_timer_info);
} }
type_init(aspeed_timer_register_types) type_init(aspeed_timer_register_types)

View File

@ -31,7 +31,7 @@ aspeed_timer_ctrl_overflow_interrupt(uint8_t i, bool enable) "Timer %" PRIu8 ":
aspeed_timer_ctrl_pulse_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d" aspeed_timer_ctrl_pulse_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
aspeed_timer_set_ctrl2(uint32_t value) "Value: 0x%" PRIx32 aspeed_timer_set_ctrl2(uint32_t value) "Value: 0x%" PRIx32
aspeed_timer_set_value(int timer, int reg, uint32_t value) "Timer %d register %d: 0x%" PRIx32 aspeed_timer_set_value(int timer, int reg, uint32_t value) "Timer %d register %d: 0x%" PRIx32
aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRIx64 ": of size %u: 0x%" PRIx64 aspeed_timer_read(uint64_t offset, uint64_t value) "From 0x%" PRIx64 ": 0x%" PRIx64
# armv7m_systick.c # armv7m_systick.c
systick_reload(void) "systick reload" systick_reload(void) "systick reload"

View File

@ -51,11 +51,20 @@
#define WDT_TIMEOUT_CLEAR (0x14 / 4) #define WDT_TIMEOUT_CLEAR (0x14 / 4)
#define WDT_RESTART_MAGIC 0x4755 #define WDT_RESTART_MAGIC 0x4755
#define WDT_SW_RESET_ENABLE 0xAEEDF123
#define AST2600_SCU_RESET_CONTROL1 (0x40 / 4) #define AST2600_SCU_RESET_CONTROL1 (0x40 / 4)
#define SCU_RESET_CONTROL1 (0x04 / 4) #define SCU_RESET_CONTROL1 (0x04 / 4)
#define SCU_RESET_SDRAM BIT(0) #define SCU_RESET_SDRAM BIT(0)
static bool aspeed_wdt_is_soc_reset_mode(const AspeedWDTState *s)
{
uint32_t mode;
mode = extract32(s->regs[WDT_CTRL], 5, 2);
return (mode == WDT_CTRL_RESET_MODE_SOC);
}
static bool aspeed_wdt_is_enabled(const AspeedWDTState *s) static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
{ {
return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE; return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
@ -199,13 +208,18 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
case WDT_TIMEOUT_STATUS: case WDT_TIMEOUT_STATUS:
case WDT_TIMEOUT_CLEAR: case WDT_TIMEOUT_CLEAR:
case WDT_RESET_MASK2: case WDT_RESET_MASK2:
case WDT_SW_RESET_CTRL:
case WDT_SW_RESET_MASK1: case WDT_SW_RESET_MASK1:
case WDT_SW_RESET_MASK2: case WDT_SW_RESET_MASK2:
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n", "%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n",
__func__, offset); __func__, offset);
break; break;
case WDT_SW_RESET_CTRL:
if (aspeed_wdt_is_soc_reset_mode(s) &&
(data == WDT_SW_RESET_ENABLE)) {
watchdog_perform_action();
}
break;
default: default:
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
@ -278,7 +292,8 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev); s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);
/* FIXME: This setting should be derived from the SCU hw strapping /*
* FIXME: This setting should be derived from the SCU hw strapping
* register SCU70 * register SCU70
*/ */
s->pclk_freq = PCLK_HZ; s->pclk_freq = PCLK_HZ;

View File

@ -39,6 +39,7 @@ struct AspeedMachineClass {
uint32_t macs_mask; uint32_t macs_mask;
void (*i2c_init)(AspeedMachineState *bmc); void (*i2c_init)(AspeedMachineState *bmc);
uint32_t uart_default; uint32_t uart_default;
bool sdhci_wp_inverted;
}; };

View File

@ -100,6 +100,11 @@ struct SDHCIState {
uint8_t sd_spec_version; uint8_t sd_spec_version;
uint8_t uhs_mode; uint8_t uhs_mode;
uint8_t vendor; /* For vendor specific functionality */ uint8_t vendor; /* For vendor specific functionality */
/*
* Write Protect pin default active low for detecting SD card
* to be protected. Set wp_inverted to invert the signal.
*/
bool wp_inverted;
}; };
typedef struct SDHCIState SDHCIState; typedef struct SDHCIState SDHCIState;

View File

@ -32,6 +32,7 @@ OBJECT_DECLARE_TYPE(AspeedTimerCtrlState, AspeedTimerClass, ASPEED_TIMER)
#define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500" #define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500"
#define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600" #define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600"
#define TYPE_ASPEED_1030_TIMER TYPE_ASPEED_TIMER "-ast1030" #define TYPE_ASPEED_1030_TIMER TYPE_ASPEED_TIMER "-ast1030"
#define TYPE_ASPEED_2700_TIMER TYPE_ASPEED_TIMER "-ast2700"
#define ASPEED_TIMER_NR_TIMERS 8 #define ASPEED_TIMER_NR_TIMERS 8

View File

@ -42,7 +42,7 @@ class AspeedTest(LinuxKernelTest):
def do_test_arm_aspeed_buildroot_poweroff(self): def do_test_arm_aspeed_buildroot_poweroff(self):
exec_command_and_wait_for_pattern(self, 'poweroff', exec_command_and_wait_for_pattern(self, 'poweroff',
'reboot: System halted'); 'System halted');
def do_test_arm_aspeed_sdk_start(self, image): def do_test_arm_aspeed_sdk_start(self, image):
self.require_netdev('user') self.require_netdev('user')

View File

@ -27,14 +27,14 @@ class AST2x00MachineSDK(QemuSystemTest):
wait_for_console_pattern(self, '## Loading kernel from FIT Image') wait_for_console_pattern(self, '## Loading kernel from FIT Image')
wait_for_console_pattern(self, 'Starting kernel ...') wait_for_console_pattern(self, 'Starting kernel ...')
ASSET_SDK_V902_AST2700 = Asset( ASSET_SDK_V903_AST2700 = Asset(
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.02/ast2700-default-obmc.tar.gz', 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.03/ast2700-default-obmc.tar.gz',
'ac969c2602f4e6bdb69562ff466b89ae3fe1d86e1f6797bb7969d787f82116a7') '91225f50d255e2905ba8d8e0c80b71b9d157c3609770c7a740cd786370d85a77')
def test_aarch64_ast2700_evb_sdk_v09_02(self): def test_aarch64_ast2700_evb_sdk_v09_03(self):
self.set_machine('ast2700-evb') self.set_machine('ast2700-evb')
self.archive_extract(self.ASSET_SDK_V902_AST2700) self.archive_extract(self.ASSET_SDK_V903_AST2700)
num_cpu = 4 num_cpu = 4
uboot_size = os.path.getsize(self.scratch_file('ast2700-default', uboot_size = os.path.getsize(self.scratch_file('ast2700-default',

View File

@ -11,15 +11,15 @@ from qemu_test import exec_command_and_wait_for_pattern
class AST2500Machine(AspeedTest): class AST2500Machine(AspeedTest):
ASSET_BR2_202311_AST2500_FLASH = Asset( ASSET_BR2_202411_AST2500_FLASH = Asset(
('https://github.com/legoater/qemu-aspeed-boot/raw/master/' ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
'images/ast2500-evb/buildroot-2023.11/flash.img'), 'images/ast2500-evb/buildroot-2024.11/flash.img'),
'c23db6160cf77d0258397eb2051162c8473a56c441417c52a91ba217186e715f') '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a')
def test_arm_ast2500_evb_buildroot(self): def test_arm_ast2500_evb_buildroot(self):
self.set_machine('ast2500-evb') self.set_machine('ast2500-evb')
image_path = self.ASSET_BR2_202311_AST2500_FLASH.fetch() image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch()
self.vm.add_args('-device', self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');

View File

@ -16,15 +16,15 @@ from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands
class AST2600Machine(AspeedTest): class AST2600Machine(AspeedTest):
ASSET_BR2_202311_AST2600_FLASH = Asset( ASSET_BR2_202411_AST2600_FLASH = Asset(
('https://github.com/legoater/qemu-aspeed-boot/raw/master/' ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
'images/ast2600-evb/buildroot-2023.11/flash.img'), 'images/ast2600-evb/buildroot-2024.11/flash.img'),
'b62808daef48b438d0728ee07662290490ecfa65987bb91294cafb1bb7ad1a68') '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609')
def test_arm_ast2600_evb_buildroot(self): def test_arm_ast2600_evb_buildroot(self):
self.set_machine('ast2600-evb') self.set_machine('ast2600-evb')
image_path = self.ASSET_BR2_202311_AST2600_FLASH.fetch() image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch()
self.vm.add_args('-device', self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');