Skip to content

Commit d3e650f

Browse files
committed
[ot] hw/riscv: ot_earlgrey: create flash & bus for spi passthrough mode
This commit creates a new internal SPI bus and CS GPIO for `ot-spi_device` to communicate with a downstream flash device in passthrough mode. This commits adds no passthrough functionality yet, just command line functionality. This is done by creating and adding a new flash device with an associated drive to the board, similar to how the other flash devices are added. The next available drive bus index was 3. The downstream flash for passthrough mode can be created like this on the command line: - `-global ot-earlgrey-board.spiflash_passthrough=<type>`, where `type` is a type of flash device from the M25P80 family, e.g `w25q256` (see `hw/block/m25p80.c` for a list) - `-drive if=mtd,file=<file>,format=raw,bus=3` to assign backing storage to the flash. Bus 3 indicates the SPI flash for OT SPI Device passthrough mode. Signed-off-by: Alice Ziuziakowska <[email protected]>
1 parent 0999199 commit d3e650f

File tree

3 files changed

+73
-4
lines changed

3 files changed

+73
-4
lines changed

hw/opentitan/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ config OT_SOCDBG_CTRL
177177

178178
config OT_SPI_DEVICE
179179
bool
180+
select SSI
180181

181182
config OT_SPI_HOST
182183
bool

hw/opentitan/ot_spi_device.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "hw/registerfields.h"
4242
#include "hw/riscv/ibex_common.h"
4343
#include "hw/riscv/ibex_irq.h"
44+
#include "hw/ssi/ssi.h"
4445
#include "trace.h"
4546

4647
#define PARAM_SRAM_DEPTH 1024u
@@ -478,6 +479,10 @@ struct OtSPIDeviceState {
478479
SpiDeviceFlash flash;
479480
SpiDeviceTpm tpm;
480481

482+
SSIBus *spi; /* SPI Bus for downstream flash in passthrough mode */
483+
/* CS signal for downstream flash in passthrough mode, active low */
484+
qemu_irq spi_cs;
485+
481486
uint32_t *spi_regs; /* Registers */
482487
uint32_t *tpm_regs; /* Registers */
483488
uint32_t *sram; /* SRAM (DPRAM on EG, E/I on DJ) */
@@ -2440,6 +2445,9 @@ static void ot_spi_device_realize(DeviceState *dev, Error **errp)
24402445

24412446
g_assert(s->ot_id);
24422447

2448+
s->spi = ssi_create_bus(DEVICE(s), "passthrough");
2449+
qdev_init_gpio_out_named(DEVICE(s), &s->spi_cs, SSI_GPIO_CS, 1);
2450+
24432451
qemu_chr_fe_set_handlers(&s->chr, &ot_spi_device_chr_can_receive,
24442452
&ot_spi_device_chr_receive,
24452453
&ot_spi_device_chr_event_hander,

hw/riscv/ot_earlgrey.c

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ enum OtEgResetRequest {
179179
enum OtEgMtdBus {
180180
OT_EG_MTD_SPI0,
181181
OT_EG_MTD_SPI1,
182-
OT_EG_MTD_SPI_COUNT,
183-
OT_EG_MTD_EFLASH = OT_EG_MTD_SPI_COUNT,
182+
OT_EG_MTD_GENERIC_SPI_COUNT,
183+
OT_EG_MTD_EFLASH = OT_EG_MTD_GENERIC_SPI_COUNT,
184+
OT_EG_MTD_SPI_PASSTHRU,
184185
};
185186

186187
/* "Parallel" flash buses */
@@ -192,6 +193,7 @@ enum OtEGBoardDevice {
192193
OT_EG_BOARD_DEV_SOC,
193194
OT_EG_BOARD_DEV_FLASH0,
194195
OT_EG_BOARD_DEV_FLASH1,
196+
OT_EG_BOARD_DEV_FLASH_PASSTHRU,
195197
OT_EG_BOARD_DEV_COUNT,
196198
};
197199

@@ -1484,7 +1486,13 @@ struct OtEGBoardState {
14841486
DeviceState **devices;
14851487

14861488
/* optional SPI data flash (type of device) */
1487-
char *spiflash[OT_EG_MTD_SPI_COUNT];
1489+
char *spiflash[OT_EG_MTD_GENERIC_SPI_COUNT];
1490+
1491+
/*
1492+
* optional downstream SPI data flash for passthrough mode
1493+
* in OT SPI Device (type of device)
1494+
*/
1495+
char *spiflash_passthru;
14881496
};
14891497

14901498
struct OtEGMachineState {
@@ -1837,6 +1845,16 @@ static void ot_eg_board_set_spiflash1(Object *obj, const char *value,
18371845
board->spiflash[OT_EG_MTD_SPI1] = g_strdup(value);
18381846
}
18391847

1848+
static void ot_eg_board_set_spiflash_passthrough(Object *obj, const char *value,
1849+
Error **errp)
1850+
{
1851+
OtEGBoardState *board = RISCV_OT_EG_BOARD(obj);
1852+
(void)errp;
1853+
1854+
g_free(board->spiflash_passthru);
1855+
board->spiflash_passthru = g_strdup(value);
1856+
}
1857+
18401858
static void ot_eg_board_child_foreach(Object *obj, ResettableChildCallback cb,
18411859
void *opaque, ResetType type)
18421860
{
@@ -1860,7 +1878,7 @@ static void ot_eg_board_realize(DeviceState *dev, Error **errp)
18601878
BusState *bus = sysbus_get_default();
18611879
qdev_realize_and_unref(soc, bus, &error_fatal);
18621880

1863-
for (unsigned fix = 0; fix < OT_EG_MTD_SPI_COUNT; fix++) {
1881+
for (unsigned fix = 0; fix < OT_EG_MTD_GENERIC_SPI_COUNT; fix++) {
18641882
const char *flash_type = board->spiflash[OT_EG_MTD_SPI0 + fix];
18651883
/*
18661884
* skip this flash slot if no device type has been defined on the QEMU
@@ -1917,6 +1935,43 @@ static void ot_eg_board_realize(DeviceState *dev, Error **errp)
19171935
g_free(flashname);
19181936
g_free(busname);
19191937
}
1938+
1939+
/* create downstream flash for OT SPI Device passthrough mode */
1940+
if (board->spiflash_passthru) {
1941+
DeviceState *pt_flash = qdev_new(board->spiflash_passthru);
1942+
if (!object_dynamic_cast(OBJECT(pt_flash), TYPE_M25P80)) {
1943+
error_setg(errp, "%s is not a SPI dataflash device",
1944+
board->spiflash_passthru);
1945+
}
1946+
1947+
/*
1948+
* OT SPI Device is the SPI host, with a "passthrough" bus for the
1949+
* downstream flash device.
1950+
*/
1951+
DeviceState *spidevice =
1952+
RISCV_OT_EG_SOC(soc)->devices[OT_EG_SOC_DEV_SPI_DEVICE];
1953+
BusState *spibus = qdev_get_child_bus(spidevice, "passthrough");
1954+
g_assert(spibus);
1955+
1956+
/* assign drive to the flash device if given */
1957+
DriveInfo *dinfo = drive_get(IF_MTD, OT_EG_MTD_SPI_PASSTHRU, 0);
1958+
if (dinfo) {
1959+
qdev_prop_set_drive_err(DEVICE(pt_flash), "drive",
1960+
blk_by_legacy_dinfo(dinfo), &error_fatal);
1961+
}
1962+
1963+
board->devices[OT_EG_BOARD_DEV_FLASH_PASSTHRU] = pt_flash;
1964+
1965+
/* the flash device is a child of the board */
1966+
object_property_add_child(OBJECT(board), "passthrough",
1967+
OBJECT(pt_flash));
1968+
/* connect the flash as a peripheral of the passthrough bus */
1969+
ssi_realize_and_unref(pt_flash, SSI_BUS(spibus), errp);
1970+
1971+
/* connect the CS line */
1972+
qemu_irq cs = qdev_get_gpio_in_named(pt_flash, SSI_GPIO_CS, 0);
1973+
qdev_connect_gpio_out_named(spidevice, SSI_GPIO_CS, 0, cs);
1974+
}
19201975
}
19211976

19221977
static void ot_eg_board_init(Object *obj)
@@ -1927,6 +1982,11 @@ static void ot_eg_board_init(Object *obj)
19271982
object_property_add_str(obj, "spiflash1", NULL, &ot_eg_board_set_spiflash1);
19281983
object_property_set_description(obj, "spiflash1",
19291984
"SPI dataflash on SPI1 bus");
1985+
object_property_add_str(obj, "spiflash_passthrough", NULL,
1986+
&ot_eg_board_set_spiflash_passthrough);
1987+
object_property_set_description(
1988+
obj, "spiflash_passthrough",
1989+
"downstream SPI dataflash for OT SPI Device in Passthrough Mode");
19301990

19311991
OtEGBoardState *s = RISCV_OT_EG_BOARD(obj);
19321992

0 commit comments

Comments
 (0)