Skip to content

Commit 043e96e

Browse files
committed
[ot] hw/riscv: ot_earlgrey: rework flash bus management.
- enables multiple SPI data flash configuration - fixes bus assignment (collisions between SPI buses and internal flash) - flash device type should now be defined as board properties - only explicitly defined flash devices are instantiated, as the OT FPGA HW enables swapping/selecting flash types Signed-off-by: Emmanuel Blot <eblot@rivosinc.com>
1 parent b333927 commit 043e96e

File tree

3 files changed

+131
-45
lines changed

3 files changed

+131
-45
lines changed

docs/opentitan/earlgrey.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ See the section "Useful execution options" for documentation about the `no_epmp_
9696
qemu-system-riscv32 -M ot-earlgrey -display none -serial mon:stdio \
9797
-object ot-rom_img,id=rom,file=rom_with_fake_keys_fpga_cw310.elf \
9898
-drive if=pflash,file=otp-rma.raw,format=raw \
99-
-drive if=mtd,bus=1,file=flash.raw,format=raw
99+
-drive if=mtd,bus=2,file=flash.raw,format=raw
100100
````
101101

102102
where `otp-rma.raw` contains the RMA OTP image and `flash.raw` contains the signed binary file of the
@@ -145,14 +145,14 @@ See [`tools.md`](tools.md)
145145
* `-display none` can be used to prevent QEMU to open a semi-graphical windows as the default
146146
console, and use the current shell instead.
147147

148-
### Flash
148+
### Embedded Flash
149149

150-
* `-drive if=mtd,bus=1,file=<filename>,format=raw` should be used to specify a path to a QEMU RAW
151-
image file used as the OpenTitan internal flash controller image. This _RAW_ file should have
152-
been generated with the [`flashgen.py`](flashgen.md) tool.
150+
* `-drive if=mtd,id=eflash,bus=2,file=<filename>,format=raw` should be used to specify a path to a
151+
QEMU RAW image file used as the OpenTitan internal flash controller image. This _RAW_ file should
152+
have been generated with the [`flashgen.py`](flashgen.md) tool.
153153

154-
Note: for now, bus 1 is assigned to the internal controller with the embedded flash storage. See
155-
also SPI Host section.
154+
Note: MTD bus 2 is assigned to the internal controller with the embedded flash storage. See also
155+
the SPI Host section.
156156

157157
### OTBN
158158

@@ -168,17 +168,21 @@ See [`tools.md`](tools.md)
168168

169169
### SPI Host
170170

171+
* `-global ot-earlgrey-board.spiflash<bus>=<flash_type>` should be used to instanciate a SPI
172+
dataflash device of the specified type to the first device (/CS0) of the specified bus.
173+
Any SPI dataflash device supported by QEMU can be used. To list the supported devices, use
174+
`grep -F 'INFO("' hw/block/m25p80.c | cut -d'"' -f2`
175+
171176
* `-drive if=mtd,bus=0,file=<filename>,format=raw` should be used to specify a path to a QEMU RAW
172-
image file used as the ISSP IS25WP128 SPI data flash backend file. This _RAW_ file should have
173-
been created with the qemu-img tool. There is no dedicated tool to populate this image file for
174-
now.
177+
image file used as the SPI data flash backend file. This _RAW_ file should have been created with
178+
the qemu-img tool. There is no dedicated tool to populate this image file for now.
175179

176180
````sh
177181
qemu-img create -f raw spi.raw 16M
178182
````
179183

180-
For now, bus 0 is assigned to the SPI Host controller with an external flash storage. See also
181-
Flash controller section.
184+
MTD bus 0 is assigned to the SPI0 Host controller and MTD bus 1 is assigned to the SPI1 Host
185+
controller. See also Embedded Flash controller section.
182186

183187
### UART
184188

hw/riscv/ot_earlgrey.c

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#include "qemu/osdep.h"
2828
#include "qapi/error.h"
2929
#include "qapi/qmp/qlist.h"
30+
#include "qom/object.h"
3031
#include "exec/address-spaces.h"
32+
#include "hw/block/flash.h"
3133
#include "hw/boards.h"
3234
#include "hw/intc/sifive_plic.h"
3335
#include "hw/jtag/tap_ctrl.h"
@@ -155,6 +157,26 @@ enum OtEgResetRequest {
155157
OT_EG_RESET_COUNT
156158
};
157159

160+
/* Data flash buses */
161+
enum OtEgMtdBus {
162+
OT_EG_MTD_SPI0,
163+
OT_EG_MTD_SPI1,
164+
OT_EG_MTD_SPI_COUNT,
165+
OT_EG_MTD_EFLASH = OT_EG_MTD_SPI_COUNT,
166+
};
167+
168+
/* "Parallel" flash buses */
169+
enum OtEgPflashBus {
170+
OT_EG_PFLASH_OTP,
171+
};
172+
173+
enum OtEGBoardDevice {
174+
OT_EG_BOARD_DEV_SOC,
175+
OT_EG_BOARD_DEV_FLASH0,
176+
OT_EG_BOARD_DEV_FLASH1,
177+
OT_EG_BOARD_DEV_COUNT,
178+
};
179+
158180
/* EarlGrey/CW310 Peripheral clock is 6 MHz */
159181
#define OT_EG_PERIPHERAL_CLK_HZ 6000000u
160182

@@ -669,6 +691,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
669691
OT_EG_SOC_GPIO_ALERT(0, 19)
670692
),
671693
.prop = IBEXDEVICEPROPDEFS(
694+
IBEX_DEV_STRING_PROP("ot_id", "spi0"),
672695
IBEX_DEV_UINT_PROP("bus-num", 0)
673696
),
674697
},
@@ -683,6 +706,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
683706
OT_EG_SOC_GPIO_ALERT(0, 20)
684707
),
685708
.prop = IBEXDEVICEPROPDEFS(
709+
IBEX_DEV_STRING_PROP("ot_id", "spi1"),
686710
IBEX_DEV_UINT_PROP("bus-num", 1)
687711
),
688712
},
@@ -1122,12 +1146,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
11221146
/* clang-format on */
11231147
};
11241148

1125-
enum OtEGBoardDevice {
1126-
OT_EG_BOARD_DEV_SOC,
1127-
OT_EG_BOARD_DEV_FLASH,
1128-
OT_EG_BOARD_DEV_COUNT,
1129-
};
1130-
11311149
/* ------------------------------------------------------------------------ */
11321150
/* Type definitions */
11331151
/* ------------------------------------------------------------------------ */
@@ -1147,7 +1165,8 @@ struct OtEGSoCState {
11471165
struct OtEGBoardState {
11481166
DeviceState parent_obj;
11491167

1150-
DeviceState **devices;
1168+
/* optional SPI data flash (type of device) */
1169+
char *spiflash[OT_EG_MTD_SPI_COUNT];
11511170
};
11521171

11531172
struct OtEGMachineState {
@@ -1182,7 +1201,7 @@ static void ot_eg_soc_dm_configure(DeviceState *dev, const IbexDeviceDef *def,
11821201
static void ot_eg_soc_flash_ctrl_configure(
11831202
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent)
11841203
{
1185-
DriveInfo *dinfo = drive_get(IF_MTD, 1, 0);
1204+
DriveInfo *dinfo = drive_get(IF_MTD, OT_EG_MTD_EFLASH, 0);
11861205
(void)def;
11871206
(void)parent;
11881207

@@ -1223,7 +1242,7 @@ static void ot_eg_soc_hart_configure(DeviceState *dev, const IbexDeviceDef *def,
12231242
static void ot_eg_soc_otp_ctrl_configure(
12241243
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent)
12251244
{
1226-
DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
1245+
DriveInfo *dinfo = drive_get(IF_PFLASH, OT_EG_PFLASH_OTP, 0);
12271246
(void)def;
12281247
(void)parent;
12291248

@@ -1401,39 +1420,100 @@ type_init(ot_eg_soc_register_types);
14011420
/* Board */
14021421
/* ------------------------------------------------------------------------ */
14031422

1423+
static void ot_eg_board_set_spiflash0(Object *obj, const char *value,
1424+
Error **errp)
1425+
{
1426+
OtEGBoardState *board = RISCV_OT_EG_BOARD(obj);
1427+
(void)errp;
1428+
1429+
g_free(board->spiflash[OT_EG_MTD_SPI0]);
1430+
board->spiflash[OT_EG_MTD_SPI0] = g_strdup(value);
1431+
}
1432+
1433+
static void ot_eg_board_set_spiflash1(Object *obj, const char *value,
1434+
Error **errp)
1435+
{
1436+
OtEGBoardState *board = RISCV_OT_EG_BOARD(obj);
1437+
(void)errp;
1438+
1439+
g_free(board->spiflash[OT_EG_MTD_SPI1]);
1440+
board->spiflash[OT_EG_MTD_SPI1] = g_strdup(value);
1441+
}
1442+
14041443
static void ot_eg_board_realize(DeviceState *dev, Error **errp)
14051444
{
14061445
OtEGBoardState *board = RISCV_OT_EG_BOARD(dev);
14071446

1408-
DeviceState *soc = board->devices[OT_EG_BOARD_DEV_SOC];
1447+
DeviceState *soc = qdev_new(TYPE_RISCV_OT_EG_SOC);
1448+
14091449
object_property_add_child(OBJECT(board), "soc", OBJECT(soc));
14101450
sysbus_realize_and_unref(SYS_BUS_DEVICE(soc), &error_fatal);
14111451

1412-
DeviceState *spihost =
1413-
RISCV_OT_EG_SOC(soc)->devices[OT_EG_SOC_DEV_SPI_HOST0];
1414-
DeviceState *flash = board->devices[OT_EG_BOARD_DEV_FLASH];
1415-
BusState *spibus = qdev_get_child_bus(spihost, "spi0");
1416-
g_assert(spibus);
1417-
1418-
DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
1419-
if (dinfo) {
1420-
qdev_prop_set_drive_err(DEVICE(flash), "drive",
1421-
blk_by_legacy_dinfo(dinfo), &error_fatal);
1452+
for (unsigned fix = 0; fix < OT_EG_MTD_SPI_COUNT; fix++) {
1453+
const char *flash_type = board->spiflash[OT_EG_MTD_SPI0 + fix];
1454+
/*
1455+
* skip this flash slot if no device type has been defined on the QEMU
1456+
* command line
1457+
*/
1458+
if (!flash_type) {
1459+
continue;
1460+
}
1461+
1462+
/* qdev_new aborts if the specified device is not supported */
1463+
DeviceState *flash = qdev_new(flash_type);
1464+
1465+
if (!object_dynamic_cast(OBJECT(flash), TYPE_M25P80)) {
1466+
error_setg(errp, "%s is not a SPI dataflash device", flash_type);
1467+
}
1468+
1469+
/*
1470+
* retrieve the SPI host controller bus. Although each SPI host only
1471+
* has one SPI bus, each bus name in QEMU needs to be unique. The SPI
1472+
* host controller uses its bus-num property as a suffix for naming its
1473+
* bus
1474+
*/
1475+
DeviceState *spihost =
1476+
RISCV_OT_EG_SOC(soc)->devices[OT_EG_SOC_DEV_SPI_HOST0 + fix];
1477+
char *busname = g_strdup_printf("spi%u", fix);
1478+
BusState *spibus = qdev_get_child_bus(spihost, busname);
1479+
g_assert(spibus);
1480+
1481+
/*
1482+
* if a "drive" property for this bus/unit pair is defined on the QEMU
1483+
* command line, assigned it to the flash device
1484+
*/
1485+
DriveInfo *dinfo = drive_get(IF_MTD, fix, 0);
1486+
if (dinfo) {
1487+
qdev_prop_set_drive_err(DEVICE(flash), "drive",
1488+
blk_by_legacy_dinfo(dinfo), &error_fatal);
1489+
}
1490+
1491+
/* the flash device is a child of the board */
1492+
char *flashname = g_strdup_printf("dataflash%u", fix);
1493+
object_property_add_child(OBJECT(board), flashname, OBJECT(flash));
1494+
/* connect it as a peripheral of the SPI host controller bus */
1495+
ssi_realize_and_unref(flash, SSI_BUS(spibus), errp);
1496+
1497+
/*
1498+
* finally, connect the first CS line of the SPI controller to control
1499+
* to select this SPI flash device
1500+
*/
1501+
qemu_irq cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
1502+
qdev_connect_gpio_out_named(spihost, SSI_GPIO_CS, 0, cs);
1503+
1504+
g_free(flashname);
1505+
g_free(busname);
14221506
}
1423-
object_property_add_child(OBJECT(board), "dataflash", OBJECT(flash));
1424-
ssi_realize_and_unref(flash, SSI_BUS(spibus), errp);
1425-
1426-
qemu_irq cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
1427-
qdev_connect_gpio_out_named(spihost, SSI_GPIO_CS, 0, cs);
14281507
}
14291508

14301509
static void ot_eg_board_init(Object *obj)
14311510
{
1432-
OtEGBoardState *s = RISCV_OT_EG_BOARD(obj);
1433-
1434-
s->devices = g_new0(DeviceState *, OT_EG_BOARD_DEV_COUNT);
1435-
s->devices[OT_EG_BOARD_DEV_SOC] = qdev_new(TYPE_RISCV_OT_EG_SOC);
1436-
s->devices[OT_EG_BOARD_DEV_FLASH] = qdev_new("is25wp128");
1511+
object_property_add_str(obj, "spiflash0", NULL, &ot_eg_board_set_spiflash0);
1512+
object_property_set_description(obj, "spiflash0",
1513+
"SPI dataflash on SPI0 bus");
1514+
object_property_add_str(obj, "spiflash1", NULL, &ot_eg_board_set_spiflash1);
1515+
object_property_set_description(obj, "spiflash1",
1516+
"SPI dataflash on SPI1 bus");
14371517
}
14381518

14391519
static void ot_eg_board_class_init(ObjectClass *oc, void *data)

include/hw/riscv/ot_earlgrey.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424

2525
#include "qom/object.h"
2626

27-
#define TYPE_RISCV_OT_EG_MACHINE MACHINE_TYPE_NAME("ot-earlgrey")
27+
#define OT_EARLGREY "ot-earlgrey"
28+
29+
#define TYPE_RISCV_OT_EG_MACHINE MACHINE_TYPE_NAME(OT_EARLGREY)
2830
OBJECT_DECLARE_SIMPLE_TYPE(OtEGMachineState, RISCV_OT_EG_MACHINE)
2931

30-
#define TYPE_RISCV_OT_EG_BOARD "riscv.ot_earlgrey.board"
32+
#define TYPE_RISCV_OT_EG_BOARD OT_EARLGREY "-board"
3133
OBJECT_DECLARE_SIMPLE_TYPE(OtEGBoardState, RISCV_OT_EG_BOARD)
3234

33-
#define TYPE_RISCV_OT_EG_SOC "riscv.ot_earlgrey.soc"
35+
#define TYPE_RISCV_OT_EG_SOC OT_EARLGREY "-soc"
3436
OBJECT_DECLARE_TYPE(OtEGSoCState, OtEGSoCClass, RISCV_OT_EG_SOC)
3537

3638
#endif /* HW_RISCV_OT_EARLGREY_H */

0 commit comments

Comments
 (0)