Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions docs/opentitan/lc_ctrl_dmi.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Darjeeling LifeCycle Controller over DTM
# LifeCycle Controller over DTM

## Communicating with the JTAG Mailbox through a JTAG connection
## Communicating with the Life Cycle Controller through a JTAG connection

In QEMU, a bridge between the Debug Transport Module (DTM) and the JTAG Mailbox is implemented
as Debug Module bridge.
In QEMU, a bridge between the Debug Transport Module (DTM) and the Life Cycle Controller is
implemented as a Debug Module bridge.

```
+----------------+
Expand All @@ -25,9 +25,16 @@ where:
`P` is the private OT bus
`D` is the debug bus

QEMU should be started with an option such as:
In Darjeeling, a top-level debug crossbar multiplexes debug access to several devices, including
the Life Cycle Controller. Therefore, there is a single DTM and Debug Module bridge. In the QEMU
implementation of Darjeeling we thus have a single JTAG server, reachable over the `taprbb`
character device. For that machine, QEMU should be started with an option such as:
`-chardev socket,id=taprbb,host=localhost,port=3335,server=on,wait=off` so that the JTAG server is
instantiated and listens for incoming connection on TCP port 3335.
instantiated and listens for incoming connections on TCP port 3335.

In Earlgrey, we have multiple JTAG TAPs, including one for the Life Cycle Controller. The Life Cycle
Controller instantiates its own DTM and Debug Module bridge. Therefore, in the QEMU implementation
of Earlgrey we use a separate character device for that JTAG server, named instead `taprbb-lc-ctrl`.

## Communicating with JTAG server and Life Cycle controller using Python

Expand Down
1 change: 1 addition & 0 deletions docs/opentitan/ot_earlgrey.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Devices in this group implement subset(s) of the real HW.
* KMAC
* Masking is not supported
* Lifecycle controller
* [LC controller](lc_ctrl_dmi.md) can be accessed through JTAG using a DM-TL bridge
* [ROM controller](ot_rom_ctrl.md)
* SRAM controller
* Initialization and scrambling from OTP key supported
Expand Down
103 changes: 99 additions & 4 deletions hw/riscv/ot_earlgrey.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@
#include "hw/jtag/tap_ctrl.h"
#include "hw/jtag/tap_ctrl_rbb.h"
#include "hw/misc/pulp_rv_dm.h"
#include "hw/opentitan/ot_address_space.h"
#include "hw/opentitan/ot_aes.h"
#include "hw/opentitan/ot_alert.h"
#include "hw/opentitan/ot_aon_timer.h"
#include "hw/opentitan/ot_ast_eg.h"
#include "hw/opentitan/ot_clkmgr.h"
#include "hw/opentitan/ot_common.h"
#include "hw/opentitan/ot_csrng.h"
#include "hw/opentitan/ot_dm_tl.h"
#include "hw/opentitan/ot_edn.h"
#include "hw/opentitan/ot_entropy_src.h"
#include "hw/opentitan/ot_flash.h"
Expand Down Expand Up @@ -100,6 +102,8 @@ static void ot_eg_soc_otp_ctrl_configure(
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent);
static void ot_eg_soc_tap_ctrl_configure(
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent);
static void ot_eg_soc_lc_ctrl_tap_ctrl_configure(
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent);
static void ot_eg_soc_spi_device_configure(
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent);
static void ot_eg_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def,
Expand All @@ -111,6 +115,14 @@ static void ot_eg_soc_usbdev_configure(
/* Constants */
/* ------------------------------------------------------------------------ */

enum OtEgMemoryRegion {
OT_EG_DEFAULT_MEMORY_REGION,
OT_EG_LC_CTRL_TAP_MEMORY_REGION,
};

#define LC_CTRL_TAP_MEMORY(_addr_) \
IBEX_MEMMAP_MAKE_REG((_addr_), OT_EG_LC_CTRL_TAP_MEMORY_REGION)

enum OtEGSocDevice {
OT_EG_SOC_DEV_ADC_CTRL,
OT_EG_SOC_DEV_AES,
Expand All @@ -121,6 +133,7 @@ enum OtEGSocDevice {
OT_EG_SOC_DEV_CSRNG,
OT_EG_SOC_DEV_DM,
OT_EG_SOC_DEV_DTM,
OT_EG_SOC_DEV_LC_CTRL_DTM,
OT_EG_SOC_DEV_EDN0,
OT_EG_SOC_DEV_EDN1,
OT_EG_SOC_DEV_ENTROPY_SRC,
Expand Down Expand Up @@ -148,13 +161,15 @@ enum OtEGSocDevice {
OT_EG_SOC_DEV_ROM_CTRL,
OT_EG_SOC_DEV_RSTMGR,
OT_EG_SOC_DEV_RV_DM,
OT_EG_SOC_DEV_DM_LC_CTRL,
OT_EG_SOC_DEV_SENSOR_CTRL,
OT_EG_SOC_DEV_SPI_DEVICE,
OT_EG_SOC_DEV_SPI_HOST0,
OT_EG_SOC_DEV_SPI_HOST1,
OT_EG_SOC_DEV_SRAM_MAIN_CTRL,
OT_EG_SOC_DEV_SYSRST_CTRL,
OT_EG_SOC_DEV_TAP_CTRL,
OT_EG_SOC_DEV_LC_CTRL_TAP_CTRL,
OT_EG_SOC_DEV_TIMER,
OT_EG_SOC_DEV_UART0,
OT_EG_SOC_DEV_UART1,
Expand Down Expand Up @@ -196,6 +211,24 @@ enum OtEGBoardDevice {
OT_EG_BOARD_DEV_COUNT,
};

/*
* <opentitan>/hw/ip/lc_ctrl/rtl/lc_ctrl.sv instantiates a DMI module (with
* abits=7) and a DMI to TL-UL adapter. Together, they create a private bus,
* exposing the LC Ctrl registers over JTAG <-> DTM <-> DMI <-> TL-UL. On the
* DMI side we have the address space [0 .. 2^7); those addresses are mapped to
* words on the TL-UL side, addressing [0 .. 2^7*4) bytes, and accessing the LC
* Ctrl registers at the appropriate (documented) offset.
*/
#define OT_EG_LC_CTRL_TAP_DMI_ABITS 7u
#define OT_EG_LC_CTRL_TAP_DMI_ADDR 0x0u
#define OT_EG_LC_CTRL_TAP_DMI_SIZE (1u << OT_EG_LC_CTRL_TAP_DMI_ABITS)
#define OT_EG_LC_CTRL_TAP_TL_ADDR 0x0u
#define OT_EG_LC_CTRL_TAP_TL_SIZE ((1u << OT_EG_LC_CTRL_TAP_DMI_ABITS) * 4u)

#define OT_EG_LC_CTRL_TAP "ot-lc_ctrl-tap"
#define OT_EG_LC_CTRL_TAP_XBAR OT_EG_LC_CTRL_TAP ".xbar"
#define OT_EG_LC_CTRL_TAP_AS OT_EG_LC_CTRL_TAP ".as"

#define OT_EG_IBEX_WRAPPER_NUM_REGIONS 2u

static const uint8_t ot_eg_pmp_cfgs[] = {
Expand Down Expand Up @@ -361,6 +394,14 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
IBEX_DEV_UINT_PROP("idcode", EG_RV_DM_TAP_IDCODE)
),
},
[OT_EG_SOC_DEV_LC_CTRL_TAP_CTRL] = {
.type = TYPE_TAP_CTRL_RBB,
.cfg = &ot_eg_soc_lc_ctrl_tap_ctrl_configure,
.prop = IBEXDEVICEPROPDEFS(
IBEX_DEV_UINT_PROP("ir_length", IBEX_TAP_IR_LENGTH),
IBEX_DEV_UINT_PROP("idcode", EG_LC_CTRL_TAP_IDCODE)
),
},
[OT_EG_SOC_DEV_DTM] = {
.type = TYPE_RISCV_DTM,
.link = IBEXDEVICELINKDEFS(
Expand All @@ -370,6 +411,15 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
IBEX_DEV_UINT_PROP("abits", 7u)
),
},
[OT_EG_SOC_DEV_LC_CTRL_DTM] = {
.type = TYPE_RISCV_DTM,
.link = IBEXDEVICELINKDEFS(
OT_EG_SOC_DEVLINK("tap-ctrl", LC_CTRL_TAP_CTRL)
),
.prop = IBEXDEVICEPROPDEFS(
IBEX_DEV_UINT_PROP("abits", OT_EG_LC_CTRL_TAP_DMI_ABITS)
),
},
[OT_EG_SOC_DEV_DM] = {
.type = TYPE_RISCV_DM,
.cfg = &ot_eg_soc_dm_configure,
Expand Down Expand Up @@ -742,7 +792,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
[OT_EG_SOC_DEV_LC_CTRL] = {
.type = TYPE_OT_LC_CTRL,
.memmap = MEMMAPENTRIES(
{ .base = 0x40140000u }
{ .base = 0x40140000u },
{ .base = LC_CTRL_TAP_MEMORY(OT_EG_LC_CTRL_TAP_TL_ADDR) }
),
.gpio = IBEXGPIOCONNDEFS(
OT_EG_SOC_RSP(OT_PWRMGR_LC, PWRMGR),
Expand Down Expand Up @@ -1371,6 +1422,19 @@ static const IbexDeviceDef ot_eg_soc_devices[] = {
OT_EG_SOC_GPIO_ALERT(0, 40)
),
},
[OT_EG_SOC_DEV_DM_LC_CTRL] = {
.type = TYPE_OT_DM_TL,
.link = IBEXDEVICELINKDEFS(
OT_EG_SOC_DEVLINK("dtm", LC_CTRL_DTM),
OT_EG_SOC_DEVLINK("tl_dev", LC_CTRL)
),
.prop = IBEXDEVICEPROPDEFS(
IBEX_DEV_UINT_PROP("dmi_addr", OT_EG_LC_CTRL_TAP_DMI_ADDR),
IBEX_DEV_UINT_PROP("dmi_size", OT_EG_LC_CTRL_TAP_DMI_SIZE),
IBEX_DEV_UINT_PROP("tl_addr", OT_EG_LC_CTRL_TAP_TL_ADDR),
IBEX_DEV_STRING_PROP("tl_as_name", OT_EG_LC_CTRL_TAP_AS)
)
},
[OT_EG_SOC_DEV_PLIC] = {
.type = TYPE_SIFIVE_PLIC,
.memmap = MEMMAPENTRIES(
Expand Down Expand Up @@ -1616,6 +1680,20 @@ static void ot_eg_soc_tap_ctrl_configure(
}
}

static void ot_eg_soc_lc_ctrl_tap_ctrl_configure(
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent)
{
(void)parent;
(void)def;

Chardev *chr;

chr = ibex_get_chardev_by_id("taprbb-lc-ctrl");
if (chr) {
qdev_prop_set_chr(dev, "chardev", chr);
}
}

static void ot_eg_soc_spi_device_configure(
DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent)
{
Expand Down Expand Up @@ -1761,9 +1839,26 @@ static void ot_eg_soc_realize(DeviceState *dev, Error **errp)
ot_eg_soc_devices,
ARRAY_SIZE(ot_eg_soc_devices));

MemoryRegion *mrs[] = { get_system_memory(), NULL, NULL, NULL };
ibex_map_devices(s->devices, mrs, ot_eg_soc_devices,
ARRAY_SIZE(ot_eg_soc_devices));
MemoryRegion *lc_ctrl_tap_mr = g_new0(MemoryRegion, 1u);
memory_region_init(lc_ctrl_tap_mr, OBJECT(dev), OT_EG_LC_CTRL_TAP_XBAR,
OT_EG_LC_CTRL_TAP_TL_SIZE);

MemoryRegion *mrs[IBEX_MEMMAP_REGIDX_COUNT] = {
[OT_EG_DEFAULT_MEMORY_REGION] = get_system_memory(),
[OT_EG_LC_CTRL_TAP_MEMORY_REGION] = lc_ctrl_tap_mr,
};
ibex_map_devices_mask(s->devices, mrs, ot_eg_soc_devices,
ARRAY_SIZE(ot_eg_soc_devices),
IBEX_MEMMAP_MAKE_REG_MASK(
OT_EG_DEFAULT_MEMORY_REGION) |
IBEX_MEMMAP_MAKE_REG_MASK(
OT_EG_LC_CTRL_TAP_MEMORY_REGION));
Object *oas;
AddressSpace *as = g_new0(AddressSpace, 1u);
address_space_init(as, lc_ctrl_tap_mr, OT_EG_LC_CTRL_TAP_AS);
oas = object_new(TYPE_OT_ADDRESS_SPACE);
object_property_add_child(OBJECT(dev), as->name, oas);
ot_address_space_set(OT_ADDRESS_SPACE(oas), as);

qdev_connect_gpio_out_named(DEVICE(s->devices[OT_EG_SOC_DEV_RSTMGR]),
OT_RSTMGR_SOC_RST, 0,
Expand Down
Loading