aspeed queue:

* New ISL69259 device model
 * New fby35 multi-SoC machine (AST1030 BIC + AST2600 BMC)
 * Aspeed GPIO fixes
 * Extension of m25p80 with write protect bits
 * More avocado tests using the Aspeed SDK
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmLQJ/kACgkQUaNDx8/7
 7KFO5BAAkqiSSQ9G3ihI51ET3+inihrw9wmN7FX5eMOxj8csLz1UbKOJ/YtjXvgt
 whfY5/iugVveUW+/X1xZmHbydec24f/umSpqqCtkPkIwCgvN4gjQAriXTK4qqx7g
 pCZoWxYeHsR19r985y//I+wFPB//Dd3Ac/1BgA4m0tdy/bK3MPLV2ocDe8d09Yfe
 wDYAFby4q8raKzMkJMibP7/phIg4hyguNAYtkSUsJChnXjK8/2ymsjlx7Xz+N1Gp
 Fynv9vaFiYOEvmDTPqbs7XMs3Qc+Sjz2RsxgaEdSI4pLk8H8hhgVueYE1ctWlpkI
 7q/g5KjXZsq6eKxNYDqU+ysY+vjdLZmO1tEmolgR+k4C+ladUYSBaI1XiGJjCmpb
 6vkM2ls1sgmb6C24e8vP64Jp/AgT6Qg7OW1Db3VcpBbQirf9SqtkXezgseOrsnXm
 Ni1uQF9NwUiRUWTA/bK4y/pSYNItoQ4KkeoAWPsiEm0d4Pezk2X+EMjJcCTQw9Zx
 BFtDxi/3rWB3imvhizynT93+rtNH7Z74kiI7iZGbZr6L2XhpEUlwoo+EOaeb4XAS
 ZEuR+kBNUMR9k4YhyF0DlvN61SuD703SdXCROsUq3EzCgza24JM4bl2IMSyv9Wdj
 DCL6yYEyf8FsJ9+KtK8A1uXc2yDcV4iGfEqOReTB5+k99ICzgEg=
 =faie
 -----END PGP SIGNATURE-----

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

aspeed queue:

* New ISL69259 device model
* New fby35 multi-SoC machine (AST1030 BIC + AST2600 BMC)
* Aspeed GPIO fixes
* Extension of m25p80 with write protect bits
* More avocado tests using the Aspeed SDK

# gpg: Signature made Thu 14 Jul 2022 15:28:09 BST
# 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-20220714' of https://github.com/legoater/qemu:
  aspeed: Add fby35-bmc slot GPIO's
  hw/gpio/aspeed: Don't let guests modify input pins
  qtest/aspeed_gpio: Add input pin modification test
  hw: m25p80: add tests for BP and TB bit write protect
  hw: m25p80: Add Block Protect and Top Bottom bits for write protect
  test/avocado/machine_aspeed.py: Add SDK tests
  docs: aspeed: Minor updates
  docs: aspeed: Add fby35 multi-SoC machine section
  aspeed: Add AST1030 (BIC) to fby35
  aspeed: fby35: Add a bootrom for the BMC
  aspeed: Add AST2600 (BMC) to fby35
  aspeed: Add fby35 skeleton
  aspeed: Make aspeed_board_init_flashes public
  aspeed: Refactor UART init for multi-SoC machines
  aspeed: Create SRAM name from first CPU index
  hw/sensor: Add Renesas ISL69259 device model
  hw/sensor: Add IC_DEVICE_ID to ISL voltage regulators
  hw/i2c/pmbus: Add idle state to return 0xff's
  aspeed: sbc: Allow per-machine settings

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2022-07-15 11:33:39 +01:00
commit 44bfcf628b
20 changed files with 763 additions and 56 deletions

View file

@ -1065,6 +1065,7 @@ F: hw/net/ftgmac100.c
F: include/hw/net/ftgmac100.h
F: docs/system/arm/aspeed.rst
F: tests/qtest/*aspeed*
F: hw/arm/fby35.c
NRF51
M: Joel Stanley <joel@jms.id.au>

View file

@ -31,7 +31,10 @@ AST2600 SoC based machines :
- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
- ``rainier-bmc`` IBM Rainier POWER10 BMC
- ``fuji-bmc`` Facebook Fuji BMC
- ``bletchley-bmc`` Facebook Bletchley BMC
- ``fby35-bmc`` Facebook fby35 BMC
- ``qcom-dc-scm-v1-bmc`` Qualcomm DC-SCM V1 BMC
- ``qcom-firework-bmc`` Qualcomm Firework BMC
Supported devices
-----------------
@ -40,7 +43,7 @@ Supported devices
* Interrupt Controller (VIC)
* Timer Controller
* RTC Controller
* I2C Controller
* I2C Controller, including the new register interface of the AST2600
* System Control Unit (SCU)
* SRAM mapping
* X-DMA Controller (basic interface)
@ -57,6 +60,10 @@ Supported devices
* LPC Peripheral Controller (a subset of subdevices are supported)
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
* ADC
* Secure Boot Controller (AST2600)
* eMMC Boot Controller (dummy)
* PECI Controller (minimal)
* I3C Controller
Missing devices
@ -68,12 +75,10 @@ Missing devices
* Super I/O Controller
* PCI-Express 1 Controller
* Graphic Display Controller
* PECI Controller
* MCTP Controller
* Mailbox Controller
* Virtual UART
* eSPI Controller
* I3C Controller
Boot options
------------
@ -154,6 +159,8 @@ Supported devices
* LPC Peripheral Controller (a subset of subdevices are supported)
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
* ADC
* Secure Boot Controller
* PECI Controller (minimal)
Missing devices
@ -161,7 +168,6 @@ Missing devices
* PWM and Fan Controller
* Slave GPIO Controller
* PECI Controller
* Mailbox Controller
* Virtual UART
* eSPI Controller
@ -182,3 +188,51 @@ To boot a kernel directly from a Zephyr build tree:
$ qemu-system-arm -M ast1030-evb -nographic \
-kernel zephyr.elf
Facebook Yosemite v3.5 Platform and CraterLake Server (``fby35``)
==================================================================
Facebook has a series of multi-node compute server designs named
Yosemite. The most recent version released was
`Yosemite v3 <https://www.opencompute.org/documents/ocp-yosemite-v3-platform-design-specification-1v16-pdf>`__.
Yosemite v3.5 is an iteration on this design, and is very similar: there's a
baseboard with a BMC, and 4 server slots. The new server board design termed
"CraterLake" includes a Bridge IC (BIC), with room for expansion boards to
include various compute accelerators (video, inferencing, etc). At the moment,
only the first server slot's BIC is included.
Yosemite v3.5 is itself a sled which fits into a 40U chassis, and 3 sleds
can be fit into a chassis. See `here <https://www.opencompute.org/products/423/wiwynn-yosemite-v3-server>`__
for an example.
In this generation, the BMC is an AST2600 and each BIC is an AST1030. The BMC
runs `OpenBMC <https://github.com/facebook/openbmc>`__, and the BIC runs
`OpenBIC <https://github.com/facebook/openbic>`__.
Firmware images can be retrieved from the Github releases or built from the
source code, see the README's for instructions on that. This image uses the
"fby35" machine recipe from OpenBMC, and the "yv35-cl" target from OpenBIC.
Some reference images can also be found here:
.. code-block:: bash
$ wget https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
$ wget https://github.com/peterdelevoryas/OpenBIC/releases/download/oby35-cl-2022.13.01/Y35BCL.elf
Since this machine has multiple SoC's, each with their own serial console, the
recommended way to run it is to allocate a pseudoterminal for each serial
console and let the monitor use stdio. Also, starting in a paused state is
useful because it allows you to attach to the pseudoterminals before the boot
process starts.
.. code-block:: bash
$ qemu-system-arm -machine fby35 \
-drive file=fby35.mtd,format=raw,if=mtd \
-device loader,file=Y35BCL.elf,addr=0,cpu-num=2 \
-serial pty -serial pty -serial mon:stdio \
-display none -S
$ screen /dev/tty0 # In a separate TMUX pane, terminal window, etc.
$ screen /dev/tty1
$ (qemu) c # Start the boot process once screen is setup.

View file

@ -26,6 +26,7 @@
#include "qemu/error-report.h"
#include "qemu/units.h"
#include "hw/qdev-clock.h"
#include "sysemu/sysemu.h"
static struct arm_boot_info aspeed_board_binfo = {
.board_id = -1, /* device-tree-only board */
@ -261,7 +262,7 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
}
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
unsigned int count, int unit0)
{
int i;
@ -301,6 +302,21 @@ static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
&error_fatal);
}
static void connect_serial_hds_to_uarts(AspeedMachineState *bmc)
{
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
AspeedSoCState *s = &bmc->soc;
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
aspeed_soc_uart_set_chr(s, amc->uart_default, serial_hd(0));
for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
if (uart == amc->uart_default) {
continue;
}
aspeed_soc_uart_set_chr(s, uart, serial_hd(i));
}
}
static void aspeed_machine_init(MachineState *machine)
{
AspeedMachineState *bmc = ASPEED_MACHINE(machine);
@ -346,8 +362,7 @@ static void aspeed_machine_init(MachineState *machine)
object_property_set_int(OBJECT(&bmc->soc), "hw-prot-key",
ASPEED_SCU_PROT_KEY, &error_abort);
}
qdev_prop_set_uint32(DEVICE(&bmc->soc), "uart-default",
amc->uart_default);
connect_serial_hds_to_uarts(bmc);
qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort);
aspeed_board_init_flashes(&bmc->soc.fmc,
@ -1343,11 +1358,23 @@ static void fby35_reset(MachineState *state)
qemu_devices_reset();
/* Board ID */
/* Board ID: 7 (Class-1, 4 slots) */
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioV5", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioV6", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioV7", false, &error_fatal);
/* Slot presence pins, inverse polarity. (False means present) */
object_property_set_bool(OBJECT(gpio), "gpioH4", false, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioH5", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioH6", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioH7", true, &error_fatal);
/* Slot 12v power pins, normal polarity. (True means powered-on) */
object_property_set_bool(OBJECT(gpio), "gpioB2", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioB3", false, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioB4", false, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioB5", false, &error_fatal);
}
static void aspeed_machine_fby35_class_init(ObjectClass *oc, void *data)
@ -1383,8 +1410,7 @@ static void aspeed_minibmc_machine_init(MachineState *machine)
object_property_set_link(OBJECT(&bmc->soc), "memory",
OBJECT(get_system_memory()), &error_abort);
qdev_prop_set_uint32(DEVICE(&bmc->soc), "uart-default",
amc->uart_default);
connect_serial_hds_to_uarts(bmc);
qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort);
aspeed_board_init_flashes(&bmc->soc.fmc,

View file

@ -144,6 +144,10 @@ static void aspeed_soc_ast1030_init(Object *obj)
object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename);
}
for (i = 0; i < sc->uarts_num; i++) {
object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
}
snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
object_initialize_child(obj, "gpio", &s->gpio, typename);
@ -159,6 +163,7 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
DeviceState *armv7m;
Error *err = NULL;
int i;
g_autofree char *sram_name = NULL;
if (!clock_has_source(s->sysclk)) {
error_setg(errp, "sysclk clock must be wired up by the board code");
@ -183,7 +188,9 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), &error_abort);
/* Internal SRAM */
memory_region_init_ram(&s->sram, NULL, "aspeed.sram", sc->sram_size, &err);
sram_name = g_strdup_printf("aspeed.sram.%d",
CPU(s->armv7m.cpu)->cpu_index);
memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, &err);
if (err != NULL) {
error_propagate(errp, err);
return;
@ -252,7 +259,9 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4));
/* UART */
aspeed_soc_uart_init(s);
if (!aspeed_soc_uart_realize(s, errp)) {
return;
}
/* Timer */
object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),

View file

@ -214,6 +214,10 @@ static void aspeed_soc_ast2600_init(Object *obj)
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);
}
snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname);
object_initialize_child(obj, "xdma", &s->xdma, typename);
@ -276,6 +280,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
Error *err = NULL;
qemu_irq irq;
g_autofree char *sram_name = NULL;
/* IO space */
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
@ -335,8 +340,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
}
/* SRAM */
memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
sc->sram_size, &err);
sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&s->cpu[0])->cpu_index);
memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, &err);
if (err) {
error_propagate(errp, err);
return;
@ -385,7 +390,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* UART */
aspeed_soc_uart_init(s);
if (!aspeed_soc_uart_realize(s, errp)) {
return;
}
/* I2C */
object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),

View file

@ -208,6 +208,10 @@ static void aspeed_soc_init(Object *obj)
TYPE_FTGMAC100);
}
for (i = 0; i < sc->uarts_num; i++) {
object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
}
snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname);
object_initialize_child(obj, "xdma", &s->xdma, typename);
@ -239,6 +243,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
AspeedSoCState *s = ASPEED_SOC(dev);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
Error *err = NULL;
g_autofree char *sram_name = NULL;
/* IO space */
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
@ -259,8 +264,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
}
/* SRAM */
memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
sc->sram_size, &err);
sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&s->cpu[0])->cpu_index);
memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, &err);
if (err) {
error_propagate(errp, err);
return;
@ -314,7 +319,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* UART */
aspeed_soc_uart_init(s);
if (!aspeed_soc_uart_realize(s, errp)) {
return;
}
/* I2C */
object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),
@ -481,8 +488,6 @@ static Property aspeed_soc_properties[] = {
MemoryRegion *),
DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_UINT32("uart-default", AspeedSoCState, uart_default,
ASPEED_DEV_UART5),
DEFINE_PROP_END_OF_LIST(),
};
@ -572,23 +577,37 @@ qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev)
return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev);
}
void aspeed_soc_uart_init(AspeedSoCState *s)
bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
{
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
int i, uart;
SerialMM *smm;
/* Attach an 8250 to the IO space as our UART */
serial_mm_init(s->memory, sc->memmap[s->uart_default], 2,
aspeed_soc_get_irq(s, s->uart_default), 38400,
serial_hd(0), DEVICE_LITTLE_ENDIAN);
for (i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
if (uart == s->uart_default) {
uart++;
for (int i = 0, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
smm = &s->uart[i];
/* Chardev property is set by the machine. */
qdev_prop_set_uint8(DEVICE(smm), "regshift", 2);
qdev_prop_set_uint32(DEVICE(smm), "baudbase", 38400);
qdev_set_legacy_instance_id(DEVICE(smm), sc->memmap[uart], 2);
qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN);
if (!sysbus_realize(SYS_BUS_DEVICE(smm), errp)) {
return false;
}
serial_mm_init(s->memory, sc->memmap[uart], 2,
aspeed_soc_get_irq(s, uart), 38400,
serial_hd(i), DEVICE_LITTLE_ENDIAN);
sysbus_connect_irq(SYS_BUS_DEVICE(smm), 0, aspeed_soc_get_irq(s, uart));
aspeed_mmio_map(s, SYS_BUS_DEVICE(smm), 0, sc->memmap[uart]);
}
return true;
}
void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr)
{
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
int i = dev - ASPEED_DEV_UART1;
g_assert(0 <= i && i < ARRAY_SIZE(s->uart) && i < sc->uarts_num);
qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
}
/*

188
hw/arm/fby35.c Normal file
View file

@ -0,0 +1,188 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com)
*
* This code is licensed under the GPL version 2 or later. See the COPYING
* file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qapi/error.h"
#include "sysemu/sysemu.h"
#include "sysemu/block-backend.h"
#include "hw/boards.h"
#include "hw/qdev-clock.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/arm/boot.h"
#define TYPE_FBY35 MACHINE_TYPE_NAME("fby35")
OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35);
struct Fby35State {
MachineState parent_obj;
MemoryRegion bmc_memory;
MemoryRegion bmc_dram;
MemoryRegion bmc_boot_rom;
MemoryRegion bic_memory;
Clock *bic_sysclk;
AspeedSoCState bmc;
AspeedSoCState bic;
bool mmio_exec;
};
#define FBY35_BMC_RAM_SIZE (2 * GiB)
#define FBY35_BMC_FIRMWARE_ADDR 0x0
static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
hwaddr offset, size_t rom_size,
Error **errp)
{
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
g_autofree void *storage = NULL;
int64_t size;
/*
* The block backend size should have already been 'validated' by
* the creation of the m25p80 object.
*/
size = blk_getlength(blk);
if (size <= 0) {
error_setg(errp, "failed to get flash size");
return;
}
if (rom_size > size) {
rom_size = size;
}
storage = g_malloc0(rom_size);
if (blk_pread(blk, 0, rom_size, storage, 0) < 0) {
error_setg(errp, "failed to read the initial flash content");
return;
}
/* TODO: find a better way to install the ROM */
memcpy(memory_region_get_ram_ptr(mr) + offset, storage, rom_size);
}
static void fby35_bmc_init(Fby35State *s)
{
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX);
memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram",
FBY35_BMC_RAM_SIZE, &error_abort);
object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
object_property_set_int(OBJECT(&s->bmc), "ram-size", FBY35_BMC_RAM_SIZE,
&error_abort);
object_property_set_link(OBJECT(&s->bmc), "memory", OBJECT(&s->bmc_memory),
&error_abort);
object_property_set_link(OBJECT(&s->bmc), "dram", OBJECT(&s->bmc_dram),
&error_abort);
object_property_set_int(OBJECT(&s->bmc), "hw-strap1", 0x000000C0,
&error_abort);
object_property_set_int(OBJECT(&s->bmc), "hw-strap2", 0x00000003,
&error_abort);
aspeed_soc_uart_set_chr(&s->bmc, ASPEED_DEV_UART5, serial_hd(0));
qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
/* Install first FMC flash content as a boot rom. */
if (drive0) {
AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0];
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
uint64_t size = memory_region_size(&fl->mmio);
if (s->mmio_exec) {
memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
&fl->mmio, 0, size);
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
boot_rom);
} else {
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
size, &error_abort);
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
boot_rom);
fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR,
size, &error_abort);
}
}
}
static void fby35_bic_init(Fby35State *s)
{
s->bic_sysclk = clock_new(OBJECT(s), "SYSCLK");
clock_set_hz(s->bic_sysclk, 200000000ULL);
memory_region_init(&s->bic_memory, OBJECT(s), "bic-memory", UINT64_MAX);
object_initialize_child(OBJECT(s), "bic", &s->bic, "ast1030-a1");
qdev_connect_clock_in(DEVICE(&s->bic), "sysclk", s->bic_sysclk);
object_property_set_link(OBJECT(&s->bic), "memory", OBJECT(&s->bic_memory),
&error_abort);
aspeed_soc_uart_set_chr(&s->bic, ASPEED_DEV_UART5, serial_hd(1));
qdev_realize(DEVICE(&s->bic), NULL, &error_abort);
aspeed_board_init_flashes(&s->bic.fmc, "sst25vf032b", 2, 2);
aspeed_board_init_flashes(&s->bic.spi[0], "sst25vf032b", 2, 4);
aspeed_board_init_flashes(&s->bic.spi[1], "sst25vf032b", 2, 6);
}
static void fby35_init(MachineState *machine)
{
Fby35State *s = FBY35(machine);
fby35_bmc_init(s);
fby35_bic_init(s);
}
static bool fby35_get_mmio_exec(Object *obj, Error **errp)
{
return FBY35(obj)->mmio_exec;
}
static void fby35_set_mmio_exec(Object *obj, bool value, Error **errp)
{
FBY35(obj)->mmio_exec = value;
}
static void fby35_instance_init(Object *obj)
{
FBY35(obj)->mmio_exec = false;
}
static void fby35_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Meta Platforms fby35";
mc->init = fby35_init;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->min_cpus = mc->max_cpus = mc->default_cpus = 3;
object_class_property_add_bool(oc, "execute-in-place",
fby35_get_mmio_exec,
fby35_set_mmio_exec);
object_class_property_set_description(oc, "execute-in-place",
"boot directly from CE0 flash device");
}
static const TypeInfo fby35_types[] = {
{
.name = MACHINE_TYPE_NAME("fby35"),
.parent = TYPE_MACHINE,
.class_init = fby35_class_init,
.instance_size = sizeof(Fby35State),
.instance_init = fby35_instance_init,
},
};
DEFINE_TYPES(fby35_types);

View file

@ -51,7 +51,8 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_soc.c',
'aspeed.c',
'aspeed_ast2600.c',
'aspeed_ast10x0.c'))
'aspeed_ast10x0.c',
'fby35.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_MSF2', if_true: files('msf2-soc.c'))

View file

@ -36,21 +36,19 @@
#include "trace.h"
#include "qom/object.h"
/* Fields for FlashPartInfo->flags */
/* erase capabilities */
#define ER_4K 1
#define ER_32K 2
/* set to allow the page program command to write 0s back to 1. Useful for
* modelling EEPROM with SPI flash command set
*/
#define EEPROM 0x100
/* 16 MiB max in 3 byte address mode */
#define MAX_3BYTES_SIZE 0x1000000
#define SPI_NOR_MAX_ID_LEN 6
/* Fields for FlashPartInfo->flags */
enum spi_flash_option_flags {
ER_4K = BIT(0),
ER_32K = BIT(1),
EEPROM = BIT(2),
HAS_SR_TB = BIT(3),
HAS_SR_BP3_BIT6 = BIT(4),
};
typedef struct FlashPartInfo {
const char *part_name;
/*
@ -251,7 +249,8 @@ static const FlashPartInfo known_devices[] = {
{ INFO("n25q512a11", 0x20bb20, 0, 64 << 10, 1024, ER_4K) },
{ INFO("n25q512a13", 0x20ba20, 0, 64 << 10, 1024, ER_4K) },
{ INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
{ INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) },
{ INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512,
ER_4K | HAS_SR_BP3_BIT6 | HAS_SR_TB) },
{ INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) },
{ INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) },
{ INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) },
@ -478,6 +477,11 @@ struct Flash {
bool reset_enable;
bool quad_enable;
bool aai_enable;
bool block_protect0;
bool block_protect1;
bool block_protect2;
bool block_protect3;
bool top_bottom_bit;
bool status_register_write_disabled;
uint8_t ear;
@ -623,12 +627,36 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t data)
{
uint32_t page = addr / s->pi->page_size;
uint8_t prev = s->storage[s->cur_addr];
uint32_t block_protect_value = (s->block_protect3 << 3) |
(s->block_protect2 << 2) |
(s->block_protect1 << 1) |
(s->block_protect0 << 0);
if (!s->write_enable) {
qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\n");
return;
}
if (block_protect_value > 0) {
uint32_t num_protected_sectors = 1 << (block_protect_value - 1);
uint32_t sector = addr / s->pi->sector_size;
/* top_bottom_bit == 0 means TOP */
if (!s->top_bottom_bit) {
if (s->pi->n_sectors <= sector + num_protected_sectors) {
qemu_log_mask(LOG_GUEST_ERROR,
"M25P80: write with write protect!\n");
return;
}
} else {
if (sector < num_protected_sectors) {
qemu_log_mask(LOG_GUEST_ERROR,
"M25P80: write with write protect!\n");
return;
}
}
}
if ((prev ^ data) & data) {
trace_m25p80_programming_zero_to_one(s, addr, prev, data);
}
@ -726,6 +754,15 @@ static void complete_collecting_data(Flash *s)
break;
case WRSR:
s->status_register_write_disabled = extract32(s->data[0], 7, 1);
s->block_protect0 = extract32(s->data[0], 2, 1);
s->block_protect1 = extract32(s->data[0], 3, 1);
s->block_protect2 = extract32(s->data[0], 4, 1);
if (s->pi->flags & HAS_SR_TB) {
s->top_bottom_bit = extract32(s->data[0], 5, 1);
}
if (s->pi->flags & HAS_SR_BP3_BIT6) {
s->block_protect3 = extract32(s->data[0], 6, 1);
}
switch (get_man(s)) {
case MAN_SPANSION:
@ -1212,6 +1249,15 @@ static void decode_new_cmd(Flash *s, uint32_t value)
case RDSR:
s->data[0] = (!!s->write_enable) << 1;
s->data[0] |= (!!s->status_register_write_disabled) << 7;
s->data[0] |= (!!s->block_protect0) << 2;
s->data[0] |= (!!s->block_protect1) << 3;
s->data[0] |= (!!s->block_protect2) << 4;
if (s->pi->flags & HAS_SR_TB) {
s->data[0] |= (!!s->top_bottom_bit) << 5;
}
if (s->pi->flags & HAS_SR_BP3_BIT6) {
s->data[0] |= (!!s->block_protect3) << 6;
}
if (get_man(s) == MAN_MACRONIX || get_man(s) == MAN_ISSI) {
s->data[0] |= (!!s->quad_enable) << 6;
@ -1552,6 +1598,11 @@ static void m25p80_reset(DeviceState *d)
s->wp_level = true;
s->status_register_write_disabled = false;
s->block_protect0 = false;
s->block_protect1 = false;
s->block_protect2 = false;
s->block_protect3 = false;
s->top_bottom_bit = false;
reset_memory(s);
}
@ -1638,6 +1689,32 @@ static const VMStateDescription vmstate_m25p80_write_protect = {
}
};
static bool m25p80_block_protect_needed(void *opaque)
{
Flash *s = (Flash *)opaque;
return s->block_protect0 ||
s->block_protect1 ||
s->block_protect2 ||
s->block_protect3 ||
s->top_bottom_bit;
}
static const VMStateDescription vmstate_m25p80_block_protect = {
.name = "m25p80/block_protect",
.version_id = 1,
.minimum_version_id = 1,
.needed = m25p80_block_protect_needed,
.fields = (VMStateField[]) {
VMSTATE_BOOL(block_protect0, Flash),
VMSTATE_BOOL(block_protect1, Flash),
VMSTATE_BOOL(block_protect2, Flash),
VMSTATE_BOOL(block_protect3, Flash),
VMSTATE_BOOL(top_bottom_bit, Flash),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_m25p80 = {
.name = "m25p80",
.version_id = 0,
@ -1670,6 +1747,7 @@ static const VMStateDescription vmstate_m25p80 = {
&vmstate_m25p80_data_read_loop,
&vmstate_m25p80_aai_enable,
&vmstate_m25p80_write_protect,
&vmstate_m25p80_block_protect,
NULL
}
};

View file

@ -268,7 +268,7 @@ static ptrdiff_t aspeed_gpio_set_idx(AspeedGPIOState *s, GPIOSets *regs)
}
static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
uint32_t value)
uint32_t value, uint32_t mode_mask)
{
uint32_t input_mask = regs->input_mask;
uint32_t direction = regs->direction;
@ -277,7 +277,8 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
uint32_t diff;
int gpio;
diff = old ^ new;
diff = (old ^ new);
diff &= mode_mask;
if (diff) {
for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) {
uint32_t mask = 1 << gpio;
@ -339,7 +340,7 @@ static void aspeed_gpio_set_pin_level(AspeedGPIOState *s, uint32_t set_idx,
value &= ~pin_mask;
}
aspeed_gpio_update(s, &s->sets[set_idx], value);
aspeed_gpio_update(s, &s->sets[set_idx], value, ~s->sets[set_idx].direction);
}
/*
@ -653,7 +654,7 @@ static void aspeed_gpio_write_index_mode(void *opaque, hwaddr offset,
reg_value = update_value_control_source(set, set->data_value,
reg_value);
set->data_read = reg_value;
aspeed_gpio_update(s, set, reg_value);
aspeed_gpio_update(s, set, reg_value, set->direction);
return;
case gpio_reg_idx_direction:
reg_value = set->direction;
@ -753,7 +754,7 @@ static void aspeed_gpio_write_index_mode(void *opaque, hwaddr offset,
__func__, offset, data, reg_idx_type);
return;
}
aspeed_gpio_update(s, set, set->data_value);
aspeed_gpio_update(s, set, set->data_value, UINT32_MAX);
return;
}
@ -799,7 +800,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data,
data &= props->output;
data = update_value_control_source(set, set->data_value, data);
set->data_read = data;
aspeed_gpio_update(s, set, data);
aspeed_gpio_update(s, set, data, set->direction);
return;
case gpio_reg_direction:
/*
@ -875,7 +876,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data,
PRIx64"\n", __func__, offset);
return;
}
aspeed_gpio_update(s, set, set->data_value);
aspeed_gpio_update(s, set, set->data_value, UINT32_MAX);
return;
}

View file

@ -261,6 +261,11 @@ void pmbus_check_limits(PMBusDevice *pmdev)
}
}
void pmbus_idle(PMBusDevice *pmdev)
{
pmdev->code = PMBUS_IDLE_STATE;
}
/* assert the status_cml error upon receipt of malformed command */
static void pmbus_cml_error(PMBusDevice *pmdev)
{
@ -980,6 +985,10 @@ static uint8_t pmbus_receive_byte(SMBusDevice *smd)
}
break;
case PMBUS_IDLE_STATE:
pmbus_send8(pmdev, PMBUS_ERR_BYTE);
break;
case PMBUS_CLEAR_FAULTS: /* Send Byte */
case PMBUS_PAGE_PLUS_WRITE: /* Block Write-only */
case PMBUS_STORE_DEFAULT_ALL: /* Send Byte */

View file

@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/qdev-properties.h"
#include "hw/misc/aspeed_sbc.h"
#include "qapi/error.h"
#include "migration/vmstate.h"
@ -19,6 +20,27 @@
#define R_STATUS (0x014 / 4)
#define R_QSR (0x040 / 4)
/* R_STATUS */
#define ABR_EN BIT(14) /* Mirrors SCU510[11] */
#define ABR_IMAGE_SOURCE BIT(13)
#define SPI_ABR_IMAGE_SOURCE BIT(12)
#define SB_CRYPTO_KEY_EXP_DONE BIT(11)
#define SB_CRYPTO_BUSY BIT(10)
#define OTP_WP_EN BIT(9)
#define OTP_ADDR_WP_EN BIT(8)
#define LOW_SEC_KEY_EN BIT(7)
#define SECURE_BOOT_EN BIT(6)
#define UART_BOOT_EN BIT(5)
/* bit 4 reserved*/
#define OTP_CHARGE_PUMP_READY BIT(3)
#define OTP_IDLE BIT(2)
#define OTP_MEM_IDLE BIT(1)
#define OTP_COMPARE_STATUS BIT(0)
/* QSR */
#define QSR_RSA_MASK (0x3 << 12)
#define QSR_HASH_MASK (0x3 << 10)
static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size)
{
AspeedSBCState *s = ASPEED_SBC(opaque);
@ -80,8 +102,17 @@ static void aspeed_sbc_reset(DeviceState *dev)
memset(s->regs, 0, sizeof(s->regs));
/* Set secure boot enabled with RSA4096_SHA256 and enable eMMC ABR */
s->regs[R_STATUS] = 0x000044C6;
s->regs[R_QSR] = 0x07C07C89;
s->regs[R_STATUS] = OTP_IDLE | OTP_MEM_IDLE;
if (s->emmc_abr) {
s->regs[R_STATUS] &= ABR_EN;
}
if (s->signing_settings) {
s->regs[R_STATUS] &= SECURE_BOOT_EN;
}
s->regs[R_QSR] = s->signing_settings;
}
static void aspeed_sbc_realize(DeviceState *dev, Error **errp)
@ -105,6 +136,12 @@ static const VMStateDescription vmstate_aspeed_sbc = {
}
};
static Property aspeed_sbc_properties[] = {
DEFINE_PROP_BOOL("emmc-abr", AspeedSBCState, emmc_abr, 0),
DEFINE_PROP_UINT32("signing-settings", AspeedSBCState, signing_settings, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void aspeed_sbc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -112,6 +149,7 @@ static void aspeed_sbc_class_init(ObjectClass *klass, void *data)
dc->realize = aspeed_sbc_realize;
dc->reset = aspeed_sbc_reset;
dc->vmsd = &vmstate_aspeed_sbc;
device_class_set_props(dc, aspeed_sbc_properties);
}
static const TypeInfo aspeed_sbc_info = {

View file

@ -15,6 +15,18 @@
static uint8_t isl_pmbus_vr_read_byte(PMBusDevice *pmdev)
{
ISLState *s = ISL69260(pmdev);
switch (pmdev->code) {
case PMBUS_IC_DEVICE_ID:
if (!s->ic_device_id_len) {
break;
}
pmbus_send(pmdev, s->ic_device_id, s->ic_device_id_len);
pmbus_idle(pmdev);
return 0;
}
qemu_log_mask(LOG_GUEST_ERROR,
"%s: reading from unsupported register: 0x%02x\n",
__func__, pmdev->code);
@ -107,6 +119,18 @@ static void raa228000_exit_reset(Object *obj)
pmdev->pages[0].read_temperature_3 = 0;
}
static void isl69259_exit_reset(Object *obj)
{
ISLState *s = ISL69260(obj);
static const uint8_t ic_device_id[] = {0x04, 0x00, 0x81, 0xD2, 0x49, 0x3c};
g_assert(sizeof(ic_device_id) <= sizeof(s->ic_device_id));
isl_pmbus_vr_exit_reset(obj);
s->ic_device_id_len = sizeof(ic_device_id);
memcpy(s->ic_device_id, ic_device_id, sizeof(ic_device_id));
}
static void isl_pmbus_vr_add_props(Object *obj, uint64_t *flags, uint8_t pages)
{
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
@ -245,6 +269,21 @@ static void raa229004_class_init(ObjectClass *klass, void *data)
isl_pmbus_vr_class_init(klass, data, 2);
}
static void isl69259_class_init(ObjectClass *klass, void *data)
{
ResettableClass *rc = RESETTABLE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
dc->desc = "Renesas ISL69259 Digital Multiphase Voltage Regulator";
rc->phases.exit = isl69259_exit_reset;
isl_pmbus_vr_class_init(klass, data, 2);
}
static const TypeInfo isl69259_info = {
.name = TYPE_ISL69259,
.parent = TYPE_ISL69260,
.class_init = isl69259_class_init,
};
static const TypeInfo isl69260_info = {
.name = TYPE_ISL69260,
.parent = TYPE_PMBUS_DEVICE,
@ -271,6 +310,7 @@ static const TypeInfo raa228000_info = {
static void isl_pmbus_vr_register_types(void)
{
type_register_static(&isl69259_info);
type_register_static(&isl69260_info);
type_register_static(&raa228000_info);
type_register_static(&raa229004_info);

View file

@ -36,12 +36,14 @@
#include "hw/misc/aspeed_lpc.h"
#include "hw/misc/unimp.h"
#include "hw/misc/aspeed_peci.h"
#include "hw/char/serial.h"
#define ASPEED_SPIS_NUM 2
#define ASPEED_EHCIS_NUM 2
#define ASPEED_WDTS_NUM 4
#define ASPEED_CPUS_NUM 2
#define ASPEED_MACS_NUM 4
#define ASPEED_UARTS_NUM 13
struct AspeedSoCState {
/*< private >*/
@ -79,7 +81,7 @@ struct AspeedSoCState {
AspeedSDHCIState emmc;
AspeedLPCState lpc;
AspeedPECIState peci;
uint32_t uart_default;
SerialMM uart[ASPEED_UARTS_NUM];
Clock *sysclk;
UnimplementedDeviceState iomem;
UnimplementedDeviceState video;
@ -175,11 +177,14 @@ enum {
};
qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
void aspeed_soc_uart_init(AspeedSoCState *s);
bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
bool aspeed_soc_dram_init(AspeedSoCState *s, Error **errp);
void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, int n, hwaddr addr);
void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev,
const char *name, hwaddr addr,
uint64_t size);
void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
unsigned int count, int unit0);
#endif /* ASPEED_SOC_H */

View file

@ -155,6 +155,7 @@ enum pmbus_registers {
PMBUS_MFR_MAX_TEMP_1 = 0xC0, /* R/W word */
PMBUS_MFR_MAX_TEMP_2 = 0xC1, /* R/W word */
PMBUS_MFR_MAX_TEMP_3 = 0xC2, /* R/W word */
PMBUS_IDLE_STATE = 0xFF,
};
/* STATUS_WORD */
@ -527,6 +528,12 @@ int pmbus_page_config(PMBusDevice *pmdev, uint8_t page_index, uint64_t flags);
*/
void pmbus_check_limits(PMBusDevice *pmdev);
/**
* Enter an idle state where only the PMBUS_ERR_BYTE will be returned
* indefinitely until a new command is issued.
*/
void pmbus_idle(PMBusDevice *pmdev);
extern const VMStateDescription vmstate_pmbus_device;
#define VMSTATE_PMBUS_DEVICE(_field, _state) { \

View file

@ -17,9 +17,22 @@ OBJECT_DECLARE_TYPE(AspeedSBCState, AspeedSBCClass, ASPEED_SBC)
#define ASPEED_SBC_NR_REGS (0x93c >> 2)
#define QSR_AES BIT(27)
#define QSR_RSA1024 (0x0 << 12)
#define QSR_RSA2048 (0x1 << 12)
#define QSR_RSA3072 (0x2 << 12)
#define QSR_RSA4096 (0x3 << 12)
#define QSR_SHA224 (0x0 << 10)
#define QSR_SHA256 (0x1 << 10)
#define QSR_SHA384 (0x2 << 10)
#define QSR_SHA512 (0x3 << 10)
struct AspeedSBCState {
SysBusDevice parent;
bool emmc_abr;
uint32_t signing_settings;
MemoryRegion iomem;
uint32_t regs[ASPEED_SBC_NR_REGS];

View file

@ -12,12 +12,17 @@
#include "hw/i2c/pmbus_device.h"
#include "qom/object.h"
#define TYPE_ISL69259 "isl69259"
#define TYPE_ISL69260 "isl69260"
#define TYPE_RAA228000 "raa228000"
#define TYPE_RAA229004 "raa229004"
#define ISL_MAX_IC_DEVICE_ID_LEN 16
struct ISLState {
PMBusDevice parent;
uint8_t ic_device_id[ISL_MAX_IC_DEVICE_ID_LEN];
uint8_t ic_device_id_len;
};
OBJECT_DECLARE_SIMPLE_TYPE(ISLState, ISL69260)

View file

@ -170,3 +170,71 @@ def test_arm_ast2600_evb_builroot(self):
exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year);
self.do_test_arm_aspeed_buidroot_poweroff()
def do_test_arm_aspeed_sdk_start(self, image, cpu_id):
self.vm.set_console()
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user')
self.vm.launch()
self.wait_for_console_pattern('U-Boot 2019.04')
self.wait_for_console_pattern('## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...')
self.wait_for_console_pattern('Booting Linux on physical CPU ' + cpu_id)
def test_arm_ast2500_evb_sdk(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:ast2500-evb
"""
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
'download/v08.01/ast2500-default-obmc.tar.gz')
image_hash = ('5375f82b4c43a79427909342a1e18b4e48bd663e38466862145d27bb358796fd')
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
algorithm='sha256')
archive.extract(image_path, self.workdir)
self.do_test_arm_aspeed_sdk_start(
self.workdir + '/ast2500-default/image-bmc', '0x0')
self.wait_for_console_pattern('ast2500-default login:')
def test_arm_ast2600_evb_sdk(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:ast2600-evb
"""
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
'download/v08.01/ast2600-default-obmc.tar.gz')
image_hash = ('f12ef15e8c1f03a214df3b91c814515c5e2b2f56119021398c1dbdd626817d15')
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
algorithm='sha256')
archive.extract(image_path, self.workdir)
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test');
self.vm.add_args('-device',
'ds1338,bus=aspeed.i2c.bus.5,address=0x32');
self.do_test_arm_aspeed_sdk_start(
self.workdir + '/ast2600-default/image-bmc', '0xf00')
self.wait_for_console_pattern('ast2600-default login:')
exec_command_and_wait_for_pattern(self, 'root', 'Password:')
exec_command_and_wait_for_pattern(self, '0penBmc', 'root@ast2600-default:~#')
exec_command_and_wait_for_pattern(self,
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device',
'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d');
exec_command_and_wait_for_pattern(self,
'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
self.vm.command('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000);
exec_command_and_wait_for_pattern(self,
'cat /sys/class/hwmon/hwmon19/temp1_input', '18000')
exec_command_and_wait_for_pattern(self,
'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device',
'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32');
year = time.strftime("%Y")
exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year);

View file

@ -28,6 +28,11 @@
#include "qapi/qmp/qdict.h"
#include "libqtest-single.h"
#define AST2600_GPIO_BASE 0x1E780000
#define GPIO_ABCD_DATA_VALUE 0x000
#define GPIO_ABCD_DIRECTION 0x004
static void test_set_colocated_pins(const void *data)
{
QTestState *s = (QTestState *)data;
@ -46,6 +51,27 @@ static void test_set_colocated_pins(const void *data)
g_assert(!qtest_qom_get_bool(s, "/machine/soc/gpio", "gpioV7"));
}
static void test_set_input_pins(const void *data)
{
QTestState *s = (QTestState *)data;
char name[16];
uint32_t value;
qtest_writel(s, AST2600_GPIO_BASE + GPIO_ABCD_DIRECTION, 0x00000000);
for (char c = 'A'; c <= 'D'; c++) {
for (int i = 0; i < 8; i++) {
sprintf(name, "gpio%c%d", c, i);
qtest_qom_set_bool(s, "/machine/soc/gpio", name, true);
}
}
value = qtest_readl(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE);
g_assert_cmphex(value, ==, 0xffffffff);
qtest_writel(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE, 0x00000000);
value = qtest_readl(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE);
g_assert_cmphex(value, ==, 0xffffffff);
}
int main(int argc, char **argv)
{
QTestState *s;
@ -56,6 +82,7 @@ int main(int argc, char **argv)
s = qtest_init("-machine ast2600-evb");
qtest_add_data_func("/ast2600/gpio/set_colocated_pins", s,
test_set_colocated_pins);
qtest_add_data_func("/ast2600/gpio/set_input_pins", s, test_set_input_pins);
r = g_test_run();
qtest_quit(s);

View file

@ -192,6 +192,24 @@ static void read_page_mem(uint32_t addr, uint32_t *page)
}
}
static void write_page_mem(uint32_t addr, uint32_t write_value)
{
spi_ctrl_setmode(CTRL_WRITEMODE, PP);
for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
writel(ASPEED_FLASH_BASE + addr + i * 4, write_value);
}
}
static void assert_page_mem(uint32_t addr, uint32_t expected_value)
{
uint32_t page[FLASH_PAGE_SIZE / 4];
read_page_mem(addr, page);
for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
g_assert_cmphex(page[i], ==, expected_value);
}
}
static void test_erase_sector(void)
{
uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE;
@ -501,6 +519,95 @@ static void test_status_reg_write_protection(void)
flash_reset();
}
static void test_write_block_protect(void)
{
uint32_t sector_size = 65536;
uint32_t n_sectors = 512;
spi_ce_ctrl(1 << CRTL_EXTENDED0);
spi_conf(CONF_ENABLE_W0);
uint32_t bp_bits = 0b0;
for (int i = 0; i < 16; i++) {
bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2);
spi_ctrl_start_user();
writeb(ASPEED_FLASH_BASE, WREN);
writeb(ASPEED_FLASH_BASE, BULK_ERASE);
writeb(ASPEED_FLASH_BASE, WREN);
writeb(ASPEED_FLASH_BASE, WRSR);
writeb(ASPEED_FLASH_BASE, bp_bits);
writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
writeb(ASPEED_FLASH_BASE, WREN);
spi_ctrl_stop_user();
uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
uint32_t protection_start = n_sectors - num_protected_sectors;
uint32_t protection_end = n_sectors;
for (int sector = 0; sector < n_sectors; sector++) {
uint32_t addr = sector * sector_size;
assert_page_mem(addr, 0xffffffff);
write_page_mem(addr, make_be32(0xabcdef12));
uint32_t expected_value = protection_start <= sector
&& sector < protection_end
? 0xffffffff : 0xabcdef12;
assert_page_mem(addr, expected_value);
}
}
flash_reset();
}
static void test_write_block_protect_bottom_bit(void)
{
uint32_t sector_size = 65536;
uint32_t n_sectors = 512;
spi_ce_ctrl(1 << CRTL_EXTENDED0);
spi_conf(CONF_ENABLE_W0);
/* top bottom bit is enabled */
uint32_t bp_bits = 0b00100 << 3;
for (int i = 0; i < 16; i++) {
bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2);
spi_ctrl_start_user();
writeb(ASPEED_FLASH_BASE, WREN);
writeb(ASPEED_FLASH_BASE, BULK_ERASE);
writeb(ASPEED_FLASH_BASE, WREN);
writeb(ASPEED_FLASH_BASE, WRSR);
writeb(ASPEED_FLASH_BASE, bp_bits);
writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
writeb(ASPEED_FLASH_BASE, WREN);
spi_ctrl_stop_user();
uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
uint32_t protection_start = 0;
uint32_t protection_end = num_protected_sectors;
for (int sector = 0; sector < n_sectors; sector++) {
uint32_t addr = sector * sector_size;
assert_page_mem(addr, 0xffffffff);
write_page_mem(addr, make_be32(0xabcdef12));
uint32_t expected_value = protection_start <= sector
&& sector < protection_end
? 0xffffffff : 0xabcdef12;
assert_page_mem(addr, expected_value);
}
}
flash_reset();
}
static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX";
int main(int argc, char **argv)
@ -529,6 +636,10 @@ int main(int argc, char **argv)
qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg);
qtest_add_func("/ast2400/smc/status_reg_write_protection",
test_status_reg_write_protection);
qtest_add_func("/ast2400/smc/write_block_protect",
test_write_block_protect);
qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit",
test_write_block_protect_bottom_bit);
flash_reset();
ret = g_test_run();