Skip to content

Commit 7b0e4d5

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 1f3601f commit 7b0e4d5

File tree

3 files changed

+72
-4
lines changed

3 files changed

+72
-4
lines changed

hw/opentitan/Kconfig

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

181181
config OT_SPI_DEVICE
182182
bool
183+
select SSI
183184

184185
config OT_SPI_HOST
185186
bool

hw/opentitan/ot_spi_device.c

Lines changed: 7 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
@@ -438,6 +439,9 @@ struct OtSPIDeviceState {
438439
SpiDeviceBus bus;
439440
SpiDeviceFlash flash;
440441

442+
SSIBus *spi; /* SPI Bus for downstream flash in passthrough mode */
443+
qemu_irq spi_cs; /* CS signal for downstream flash in passthrough mode */
444+
441445
uint32_t *spi_regs; /* Registers */
442446
uint32_t *tpm_regs; /* Registers */
443447
uint32_t *sram; /* SRAM (DPRAM on EG, E/I on DJ) */
@@ -2176,6 +2180,9 @@ static void ot_spi_device_realize(DeviceState *dev, Error **errp)
21762180

21772181
g_assert(s->ot_id);
21782182

2183+
s->spi = ssi_create_bus(DEVICE(s), "passthrough");
2184+
qdev_init_gpio_out_named(DEVICE(s), &s->spi_cs, SSI_GPIO_CS, 1);
2185+
21792186
qemu_chr_fe_set_handlers(&s->chr, &ot_spi_device_chr_can_receive,
21802187
&ot_spi_device_chr_receive,
21812188
&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

@@ -1481,7 +1483,13 @@ struct OtEGBoardState {
14811483
DeviceState **devices;
14821484

14831485
/* optional SPI data flash (type of device) */
1484-
char *spiflash[OT_EG_MTD_SPI_COUNT];
1486+
char *spiflash[OT_EG_MTD_GENERIC_SPI_COUNT];
1487+
1488+
/*
1489+
* optional downstream SPI data flash for passthrough mode
1490+
* in OT SPI Device (type of device)
1491+
*/
1492+
char *spiflash_passthru;
14851493
};
14861494

14871495
struct OtEGMachineState {
@@ -1834,6 +1842,16 @@ static void ot_eg_board_set_spiflash1(Object *obj, const char *value,
18341842
board->spiflash[OT_EG_MTD_SPI1] = g_strdup(value);
18351843
}
18361844

1845+
static void ot_eg_board_set_spiflash_passthrough(Object *obj, const char *value,
1846+
Error **errp)
1847+
{
1848+
OtEGBoardState *board = RISCV_OT_EG_BOARD(obj);
1849+
(void)errp;
1850+
1851+
g_free(board->spiflash_passthru);
1852+
board->spiflash_passthru = g_strdup(value);
1853+
}
1854+
18371855
static void ot_eg_board_child_foreach(Object *obj, ResettableChildCallback cb,
18381856
void *opaque, ResetType type)
18391857
{
@@ -1857,7 +1875,7 @@ static void ot_eg_board_realize(DeviceState *dev, Error **errp)
18571875
BusState *bus = sysbus_get_default();
18581876
qdev_realize_and_unref(soc, bus, &error_fatal);
18591877

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

19191974
static void ot_eg_board_init(Object *obj)
@@ -1924,6 +1979,11 @@ static void ot_eg_board_init(Object *obj)
19241979
object_property_add_str(obj, "spiflash1", NULL, &ot_eg_board_set_spiflash1);
19251980
object_property_set_description(obj, "spiflash1",
19261981
"SPI dataflash on SPI1 bus");
1982+
object_property_add_str(obj, "spiflash_passthrough", NULL,
1983+
&ot_eg_board_set_spiflash_passthrough);
1984+
object_property_set_description(
1985+
obj, "spiflash_passthrough",
1986+
"downstream SPI dataflash for OT SPI Device in Passthrough Mode");
19271987

19281988
OtEGBoardState *s = RISCV_OT_EG_BOARD(obj);
19291989

0 commit comments

Comments
 (0)