diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index b43e3cb0fd2d..6ec103bb713e 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -73,10 +73,7 @@ jobs: uses: actions/checkout@v4 - name: Check execution run: | - clang-format-16 -i \ - hw/opentitan/*.c hw/opentitan/*.h include/hw/opentitan/*.h \ - hw/riscv/ibex*.c include/hw/riscv/ibex*.h target/riscv/ibex*.c \ - hw/riscv/ot_*.c include/hw/riscv/ot_*.h + scripts/opentitan/ot-format.sh --ci -i lint-clang: runs-on: ubuntu-latest @@ -100,11 +97,7 @@ jobs: - name: Clang tidy # Expect many warnings/errors (accounted but not reported) from included QEMU files run: | - clang-tidy -p build-clang \ - hw/opentitan/*.c \ - hw/riscv/ot_*.c \ - hw/riscv/ibex*.c \ - target/riscv/ibex_csr.c + scripts/opentitan/ot-tidy.sh --ci -p build-clang test-clang: runs-on: ubuntu-latest diff --git a/.gitlab-ci.d/opentitan/bmref.yml b/.gitlab-ci.d/opentitan/bmref.yml deleted file mode 100644 index 403c2635b384..000000000000 --- a/.gitlab-ci.d/opentitan/bmref.yml +++ /dev/null @@ -1,2 +0,0 @@ -variables: - BAREMETAL_REF: "240207-2" diff --git a/.gitlab-ci.d/opentitan/build.yml b/.gitlab-ci.d/opentitan/build.yml index 0b7e3feff26f..f8d885d2b49e 100644 --- a/.gitlab-ci.d/opentitan/build.yml +++ b/.gitlab-ci.d/opentitan/build.yml @@ -23,7 +23,7 @@ build-clang: - git clean -dffx subprojects - mkdir build - cd build - - ../configure --cc=clang --disable-werror $QEMU_BUILD_OPTS + - ../configure --cc=clang-16 --disable-werror $QEMU_BUILD_OPTS --target-list=riscv32-softmmu,riscv64-softmmu,x86_64-linux-user - ninja - ninja qemu-img @@ -62,7 +62,7 @@ format: - qemu_ot stage: build script: - - scripts/opentitan/ot-format.sh -i $(tr '\n' ' ' < .gitlab-ci.d/opentitan/$CLANG_FORMAT_CONF) + - scripts/opentitan/ot-format.sh --ci -i - git status -s - test $(git status -s | wc -l) -eq 0 @@ -72,4 +72,4 @@ tidy: stage: build needs: ["build-clang"] script: - - scripts/opentitan/ot-tidy.sh -p build $(tr '\n' ' ' < .gitlab-ci.d/opentitan/$CLANG_TIDY_CONF) + - scripts/opentitan/ot-tidy.sh --ci -p build diff --git a/.gitlab-ci.d/opentitan/ot-bmtests.yml b/.gitlab-ci.d/opentitan/ot-bmtests.yml index 27fa9d5bd926..cfbc86604c87 100644 --- a/.gitlab-ci.d/opentitan/ot-bmtests.yml +++ b/.gitlab-ci.d/opentitan/ot-bmtests.yml @@ -19,7 +19,7 @@ baremetal-eg-tests: - zstd -d --stdout ot-eg-bmtest.tar.zst | tar xf - -C ${BASEDIR} - find ${BASEDIR} - scripts/opentitan/pyot.py -vv -c ${BASEDIR}/data/qemu/pyot-ot-earlgrey.hjson - -w ot-earlgrey.csv -R -T 3 -F '!aes-kat*' + -w ot-earlgrey.csv -R -T 3 -F '*' -F '!aes-kat*' artifacts: public: false expire_in: 1 year diff --git a/.gitlab-ci.d/opentitan/qemu-ot.yml b/.gitlab-ci.d/opentitan/qemu-ot.yml index 8afa03b04b07..54776cf727c5 100644 --- a/.gitlab-ci.d/opentitan/qemu-ot.yml +++ b/.gitlab-ci.d/opentitan/qemu-ot.yml @@ -1,10 +1,8 @@ variables: + BAREMETAL_REF: "240223-1" QEMU_BUILD_OPTS: "" - CLANG_FORMAT_CONF: "ot.clang_format" - CLANG_TIDY_CONF: "ot.clang_tidy" include: - - local: '/.gitlab-ci.d/opentitan/bmref.yml' - local: '/.gitlab-ci.d/opentitan/build.yml' - local: '/.gitlab-ci.d/opentitan/ot-smoke.yml' - local: '/.gitlab-ci.d/opentitan/ot-bmtests.yml' diff --git a/docs/opentitan/darjeeling.md b/docs/opentitan/darjeeling.md index 4efc81aaf493..fe4d29911e0d 100644 --- a/docs/opentitan/darjeeling.md +++ b/docs/opentitan/darjeeling.md @@ -50,6 +50,7 @@ Devices in this group implement subset(s) of the real HW. * KMAC * Side loading is not supported * Lifecycle controller + * [LC controller](lc_ctrl_dmi.md) can be accessed through JTAG using a DM-TL bridge * Escalation is not supported * Power Manager * Fast FSM is partially supported, Slow FSM is bypassed @@ -143,6 +144,12 @@ See [`tools.md`](tools.md) alternative to allow the Ibex core to execute guest code is to provide a valid OTP image with one of the expected LifeCycle state, such as TestUnlock*, Dev, Prod or RMA. +* `-global ot-ibex_wrapper-dj.lc-ignore-ids=` acts as `lc-ignore`, enabling the selection of + specific ibex wrapper instance based on their unique identifiers. See `ot_id` property in the + machine definition file for a list of valid identifiers. `` should be defined as a comma- + separated list of valid identifiers. It is only possible to ignore LifeCycle states with this + option, not to enforce them. + * `-cpu lowrisc-ibex,x-zbr=false` can be used to force disable the Zbr experimental-and-deprecated RISC-V bitmap extension for CRC32 extension. diff --git a/docs/opentitan/jtagmbx.md b/docs/opentitan/jtagmbx.md index 755d530dba5c..d918739e91a3 100644 --- a/docs/opentitan/jtagmbx.md +++ b/docs/opentitan/jtagmbx.md @@ -31,6 +31,46 @@ where: QEMU should be started with an option such as `-jtag tcp::3335` so that the JTAG server is instantiated and listen for incoming connection on TCP port 3335. +#### macOS + +If you want to avoid the boring pop-up window from macOS +``` +Do you want the application “qemu-system-riscv32” to accept incoming network connections? +``` +restrict the listening interfaces to the localhost with `-jtag tcp:localhost:3335` as QEMU defaults +to listening on all interfaces, _i.e._ 0.0.0.0 + +## Communicating with JTAG server and JTAG MailBox using Python + +OpenTitan implementation provides JTAG/DTM/DMI/Mailbox stack available as Python modules: + +* jtag/tap module is available from `scripts/jtag` directory +* dtm/dmi and jtag mailbox modules are available from `scripts/opentitan` directory + +Python snippet to create a communication channel with the VM JTAG mailbox: + +````py +from socket import create_connection +from jtag.bitbang import JtagBitbangController +from jtag.jtag import JtagEngine +from ot.dtm import DebugTransportModule +from ot.mailbox.jtag import JtagMbox + +sock = create_connection(('localhost', 3335), timeout=1.0) +ctrl = JtagBitbangController(sock) +eng = JtagEngine(ctrl) +ctrl.tap_reset(True) +dtm = DebugTransportModule(eng, 5) # IR length depends on the actual machine +version, abits = dtm['dtmcs'].dmi_version, dtm['dtmcs'].abits +print(f'DTM: v{version[0]}.{version[1]}, {abits} bits') +dtm['dtmcs'].dmireset() +mbj = JtagMbox(dtm, 0x2200 >> 2) + +# See ot.mailbox.sysmbox.SysMbox for mailbox communication API +```` + +## Communicating with JTAG server using OpenOCD + It is possible from OpenOCD running a host to connect to the embedded JTAG server using the `remote_bitbang` protocol, using a configuration script such as diff --git a/docs/opentitan/lc_ctrl_dmi.md b/docs/opentitan/lc_ctrl_dmi.md new file mode 100644 index 000000000000..e3732d8bd2c9 --- /dev/null +++ b/docs/opentitan/lc_ctrl_dmi.md @@ -0,0 +1,67 @@ +# Darjeeling LifeCycle Controller over DMI + +## Communicating with the JTAG Mailbox through a JTAG connection + +In QEMU, a bridge between the Debug Module Interface (DMI) and the JTAG Mailbox is implemented +as Debug Module bridge. + +``` ++----------------+ +| Host (OpenOCD) | ++----------------+ + | + | TCP connection ("bitbang mode") + | ++-----|-----------------------------------------------------------------------------------+ +| v | +| +-------------+ +-----+ +----------+ +---------+ +------+ | +| | JTAG server |---->| DMI |---->| ot_dm_tl |====D====| LC Ctrl |====P====| Hart | | +| +-------------+ +-----+ +----------+ +---------+ +------+ | +| QEMU| ++-----------------------------------------------------------------------------------------+ +``` + +where: + `P` is the private OT bus + `D` is the debug bus + +QEMU should be started with an option such as `-jtag tcp::3335` so that the JTAG server is +instantiated and listen for incoming connection on TCP port 3335. + +#### macOS + +If you want to avoid the boring pop-up window from macOS +``` +Do you want the application “qemu-system-riscv32” to accept incoming network connections? +``` +restrict the listening interfaces to the localhost with `-jtag tcp:localhost:3335` as QEMU defaults +to listening on all interfaces, _i.e._ 0.0.0.0 + +## Communicating with JTAG server and Life Cycle controller using Python + +OpenTitan implementation provides JTAG/DTM/DMI/Mailbox stack available as Python modules: + +* jtag/tap module is available from `scripts/jtag` directory +* dtm/dmi and jtag mailbox modules are available from `scripts/opentitan` directory + +Python snippet to create a communication channel with the VM JTAG mailbox: + +````py +from socket import create_connection +from jtag.bitbang import JtagBitbangController +from jtag.jtag import JtagEngine +from ot.dtm import DebugTransportModule +from ot.lc_ctrl.lcdmi import LifeCycleController + +sock = create_connection(('localhost', 3335), timeout=1.0) +ctrl = JtagBitbangController(sock) +eng = JtagEngine(ctrl) +ctrl.tap_reset(True) +dtm = DebugTransportModule(eng, 5) # IR length depends on the actual machine +version, abits = dtm['dtmcs'].dmi_version, dtm['dtmcs'].abits +print(f'DTM: v{version[0]}.{version[1]}, {abits} bits') +dtm['dtmcs'].dmireset() +lc_ctrl = LifeCycleController(dtm, 0x3000 >> 2) + +# See LifeCycleController for LC controller communication API +```` diff --git a/docs/opentitan/tools.md b/docs/opentitan/tools.md index e9a3e3e6ab0a..2421fe70d803 100644 --- a/docs/opentitan/tools.md +++ b/docs/opentitan/tools.md @@ -40,6 +40,14 @@ directory to help with these tasks. * `present.py` implements the Present 128-bit scrambler/descrambler used in OTP image files for HW digest verification. * `treillis/` directory contains the test application to test the [GPIO](gpio.md) device. +* [`uartmux.py`](uartmux.md) is a tiny stream wrapper to help dealing with multiple QEMU output + streams, typically multiple virtual UARTs. + +## Python modules + +* Available from `scripts/jtag` and `scripts/opentitan/ot` +* [JTAG mailbox](jtagmbx.md) provides an API to access the system side of the mailbox over JTAG/DMI +* [LC DMI](lc_ctrl_dmi.md) provides an API to control the Life Cycle controller over JTAG/DMI ## Configuration files diff --git a/docs/opentitan/uartmux.md b/docs/opentitan/uartmux.md new file mode 100644 index 000000000000..5b3f5636c470 --- /dev/null +++ b/docs/opentitan/uartmux.md @@ -0,0 +1,58 @@ +# `uartmux.py` + +`uartmux.py` is a tiny stream wrapper to help dealing with multiple QEMU output streams, typically multiple virtual UARTs. + +## Usage + +````text +usage: uartmux.py [-h] [-i IFACE] [-p PORT] [-c CHANNEL] [-v] [-d] [name ...] + +QEMU UART muxer. + +positional arguments: + name assign name to input connection + +options: + -h, --help show this help message and exit + -i IFACE, --iface IFACE + specify TCP interface to listen to (default: localhost) + -p PORT, --port PORT specify TCP port to listen to (default: 9000) + -c CHANNEL, --channel CHANNEL + expected comm channel count(default: 3) + -s SEPARATOR, --separator SEPARATOR + repeat separator between each session + -v, --verbose increase verbosity + -d, --debug enable debug mode +```` + +`uartmux.py` may be used with QEMU character devices, _i.e._ `chardev` defined as network streams, +such as `-chardev socket`. + +`uartmux.py` listens on multiple input streams, and prints them one line at a time, colorizing each +stream with a different color when an ANSI terminal is used. + +It enables a coherent output log when multiple virtual UARTs are emitting at once. + +### Arguments + +* `name` optional name(s) for prexifing each log message line with the known channel name +* `-c` / `--channel` how many input streams are expected, in order to assign the same ANSI color + to the same input stream across subsequence QEMU sessions. Note that if not defined, default to + the count of defined names +* `-d` / `--debug` only useful to debug the script, reports any Python traceback to the standard + error stream. +* `-i` / `--iface` select an alternative interface for listening on, default to localhost +* `-p` / `--port` select an altenative TCP port for listening on, default to 9000 +* `-s` / `--separator` emit this separator between each detected QEMU session +* `-v` / `--verbose` can be repeated to increase verbosity of the script, mostly for debug purpose. + +### Example + +QEMU using two virtual UART output identified as `uart0` and `uart1`: + +* run `uartmux.py uart0 uart1` in one terminal +* run QEMU in another terminal with the following option switches: + ``` + -chardev socket,id=uart0,host=127.0.0.1,port=9000 + -chardev socket,id=uart1,host=127.0.0.1,port=9000 + ``` diff --git a/hw/opentitan/ot_aes.c b/hw/opentitan/ot_aes.c index ea95756f9234..ad71d1ec38ec 100644 --- a/hw/opentitan/ot_aes.c +++ b/hw/opentitan/ot_aes.c @@ -905,7 +905,7 @@ static void ot_aes_process_cond(OtAESState *s) * AES throughput. */ timer_del(s->retard_timer); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->retard_timer, (int64_t)(now + OT_AES_RETARD_DELAY_NS)); } else { @@ -1278,8 +1278,7 @@ static void ot_aes_init(Object *obj) ibex_qdev_init_irq(obj, &s->clkmgr, OT_CLOCK_ACTIVE); s->process_bh = qemu_bh_new(&ot_aes_handle_process, s); - s->retard_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_aes_handle_process, s); + s->retard_timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_aes_handle_process, s); } static void ot_aes_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_aon_timer.c b/hw/opentitan/ot_aon_timer.c index c8891b63801c..32c42127c4b8 100644 --- a/hw/opentitan/ot_aon_timer.c +++ b/hw/opentitan/ot_aon_timer.c @@ -34,6 +34,7 @@ #include "qemu/timer.h" #include "hw/opentitan/ot_alert.h" #include "hw/opentitan/ot_aon_timer.h" +#include "hw/opentitan/ot_common.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" @@ -200,7 +201,7 @@ static void ot_aon_timer_update_irqs(OtAonTimerState *s) static void ot_aon_timer_rearm_wkup(OtAonTimerState *s, bool reset_origin) { - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); if (reset_origin) { s->wkup_origin_ns = now; @@ -239,7 +240,7 @@ static void ot_aon_timer_wkup_cb(void *opaque) static void ot_aon_timer_rearm_wdog(OtAonTimerState *s, bool reset_origin) { - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); if (reset_origin) { s->wdog_origin_ns = now; @@ -306,14 +307,14 @@ static uint64_t ot_aon_timer_read(void *opaque, hwaddr addr, unsigned size) break; case R_WKUP_COUNT: { uint64_t now = ot_aon_timer_is_wkup_enabled(s) ? - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) : + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) : s->wkup_origin_ns; val32 = ot_aon_timer_get_wkup_count(s, now); break; } case R_WDOG_COUNT: { uint64_t now = ot_aon_timer_is_wdog_enabled(s) ? - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) : + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) : s->wdog_origin_ns; val32 = ot_aon_timer_get_wdog_count(s, now); break; @@ -368,7 +369,7 @@ static void ot_aon_timer_write(void *opaque, hwaddr addr, uint64_t value, /* stop timer */ timer_del(s->wkup_timer); /* save current count */ - uint32_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + uint32_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); s->regs[R_WKUP_COUNT] = ot_aon_timer_get_wkup_count(s, now); s->wkup_origin_ns = now; } @@ -401,7 +402,7 @@ static void ot_aon_timer_write(void *opaque, hwaddr addr, uint64_t value, /* stop timer */ timer_del(s->wdog_timer); /* save current count */ - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); s->regs[R_WDOG_COUNT] = ot_aon_timer_get_wdog_count(s, now); s->wdog_origin_ns = now; } @@ -435,7 +436,7 @@ static void ot_aon_timer_write(void *opaque, hwaddr addr, uint64_t value, * schedule the timer for the next peripheral clock tick to check again * for interrupt condition */ - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); int64_t next = ot_aon_timer_compute_next_timeout(s, now, 0); if (change & INTR_WKUP_TIMER_EXPIRED_MASK) { timer_mod_anticipate(s->wkup_timer, next); @@ -503,10 +504,8 @@ static void ot_aon_timer_init(Object *obj) TYPE_OT_AON_TIMER, REGS_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); - s->wkup_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, &ot_aon_timer_wkup_cb, s); - s->wdog_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, &ot_aon_timer_wdog_cb, s); + s->wkup_timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_aon_timer_wkup_cb, s); + s->wdog_timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_aon_timer_wdog_cb, s); } static void ot_aon_timer_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_ast_dj.c b/hw/opentitan/ot_ast_dj.c index 47df01e29bca..cec5d4838583 100644 --- a/hw/opentitan/ot_ast_dj.c +++ b/hw/opentitan/ot_ast_dj.c @@ -36,6 +36,7 @@ #include "qemu/typedefs.h" #include "qapi/error.h" #include "hw/opentitan/ot_ast_dj.h" +#include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_random_src.h" #include "hw/qdev-properties-system.h" #include "hw/qdev-properties.h" @@ -175,8 +176,17 @@ static int ot_ast_dj_get_random(OtRandomSrcIf *dev, int genid, } if (!rnd->avail) { + /* not ready */ trace_ot_ast_no_entropy(0); - return 1; + int wait_ns; + if (timer_pending(s->random.timer)) { + wait_ns = 1; + } else { + /* computed delay fits into a 31-bit value */ + wait_ns = (int)(timer_expire_time_ns(s->random.timer) - + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT)); + } + return wait_ns; } memcpy(random, rnd->buffer, OT_RANDOM_SRC_DWORD_COUNT * sizeof(uint64_t)); @@ -185,7 +195,7 @@ static int ot_ast_dj_get_random(OtRandomSrcIf *dev, int genid, /* note: fips compliancy is only simulated here for now */ *fips = true; - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(rnd->timer, (int64_t)(now + OT_AST_DJ_RANDOM_FILL_RATE_NS)); return 0; @@ -403,7 +413,7 @@ static void ot_ast_dj_reset(DeviceState *dev) s->regsa[R_REGA37] = 0x25u; s->regsa[R_REGAL] = 0x26u; - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(rnd->timer, (int64_t)(now + OT_AST_DJ_RANDOM_FILL_RATE_NS)); } @@ -420,8 +430,7 @@ static void ot_ast_dj_init(Object *obj) OtASTDjRandom *rnd = &s->random; - rnd->timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_ast_dj_random_scheduler, s); + rnd->timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_ast_dj_random_scheduler, s); rnd->buffer = g_new0(uint64_t, OT_RANDOM_SRC_DWORD_COUNT); } diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index 675581e1e9e3..49ebcd9cf185 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -210,13 +210,6 @@ static_assert(OT_CSRNG_AES_BLOCK_SIZE + OT_CSRNG_AES_KEY_SIZE == #define SW_INSTANCE_ID OT_CSRNG_HW_APP_MAX -#define CMD_EXECUTE_DELAY_NS 500000u /* 500 us */ - -#define MAX_GENERATION_DELAY_NS 700000000u /* 0.7 s */ -#define MAX_GENERATION_COUNT 4096u -/* no need for rounding up, as processing takes time anyway */ -#define PACKET_GENERATION_DELAY_NS \ - (MAX_GENERATION_DELAY_NS / MAX_GENERATION_COUNT) #define ENTROPY_SRC_INITIAL_REQUEST_COUNT 5u enum { @@ -228,7 +221,7 @@ typedef enum { CSRNG_CMD_STALLED = -2, /* entropy stack is stalled */ CSRNG_CMD_ERROR = -1, /* command error, not recoverable */ CSRNG_CMD_OK = 0, /* command completed ok */ - CSRNG_CMD_RETRY = 1, /* command cannot be executed at the moment */ + CSRNG_CMD_RETRY = 1, /* command cannot be executed for now */ CSRNG_CMD_DEFERRED = 2, /* command completion deferred */ } OtCSRNDCmdResult; @@ -260,6 +253,7 @@ typedef struct { unsigned reseed_counter; unsigned rem_packet_count; /* remaining packets to generate */ bool instantiated; + bool seeded; /* ready to generate randomness */ bool fips; } OtCSRNGDrng; @@ -292,8 +286,8 @@ struct OtCSRNGState { MemoryRegion mmio; IbexIRQ irqs[PARAM_NUM_IRQS]; IbexIRQ alerts[PARAM_NUM_ALERTS]; - qemu_irq entropy_state; - QEMUTimer *cmd_scheduler; + QEMUBH *cmd_scheduler; + QEMUTimer *entropy_scheduler; uint32_t *regs; bool enabled; @@ -301,6 +295,7 @@ struct OtCSRNGState { bool read_int_granted; bool es_available; uint32_t scheduled_cmd; + unsigned entropy_delay; unsigned es_retry_count; unsigned state_db_ix; int entropy_gennum; @@ -441,7 +436,8 @@ int ot_csrng_push_command(OtCSRNGState *s, unsigned app_id, cmd_request); if (QSIMPLEQ_EMPTY(&s->cmd_requests)) { - timer_del(s->cmd_scheduler); + qemu_bh_cancel(s->cmd_scheduler); + timer_del(s->entropy_scheduler); } } } @@ -535,7 +531,7 @@ static void ot_csrng_drng_increment(OtCSRNGDrng *drng) } } -static OtCSRNDCmdResult ot_csrng_drng_instanciate( +static OtCSRNDCmdResult ot_csrng_drng_instantiate( OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) { OtCSRNGDrng *drng = &inst->drng; @@ -560,6 +556,17 @@ static OtCSRNDCmdResult ot_csrng_drng_instanciate( res = ot_csrng_drng_reseed(inst, rand_dev, flag0); if (res) { drng->instantiated = false; + return res; + } + + if (inst->hw.genbits_ready) { + /* + * a HW client app of this instance has already requested randomness + * through #ot_csrng_hwapp_ready_irq. This request had been deferred + * till the instanciation stage has completed, it is now safe to + * schedule the actual generation + */ + qemu_bh_schedule(inst->hw.filler_bh); } return res; @@ -574,6 +581,7 @@ static void ot_csrng_drng_uninstantiate(OtCSRNGInstance *inst) } drng->instantiated = false; + drng->seeded = false; drng->fips = false; drng->rem_packet_count = 0; @@ -581,7 +589,7 @@ static void ot_csrng_drng_uninstantiate(OtCSRNGInstance *inst) memset(drng->v_counter, 0, sizeof(drng->v_counter)); } -static int ot_csrng_drng_update(OtCSRNGInstance *inst) +static void ot_csrng_drng_update(OtCSRNGInstance *inst) { OtCSRNGDrng *drng = &inst->drng; @@ -627,8 +635,6 @@ static int ot_csrng_drng_update(OtCSRNGInstance *inst) OT_CSRNG_AES_KEY_SIZE); xtrace_ot_csrng_show_buffer(appid, "n-V", drng->v_counter, OT_CSRNG_AES_BLOCK_SIZE); - - return 0; } static OtCSRNDCmdResult @@ -637,6 +643,8 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) OtCSRNGDrng *drng = &inst->drng; g_assert(drng->instantiated); + drng->seeded = false; + if (!flag0) { if (!inst->parent->es_available) { qemu_log_mask(LOG_GUEST_ERROR, @@ -654,13 +662,18 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) uint64_t entropy[OT_RANDOM_SRC_DWORD_COUNT]; int res; bool fips; - xtrace_ot_csrng_info("request ES entropy w/ generation", - s->entropy_gennum); - + trace_ot_csrng_request_entropy(ot_csrng_get_slot(inst), + s->entropy_gennum); OtRandomSrcIfClass *cls = OT_RANDOM_SRC_IF_GET_CLASS(rand_dev); OtRandomSrcIf *randif = OT_RANDOM_SRC_IF(rand_dev); res = cls->get_random_values(randif, s->entropy_gennum, entropy, &fips); if (res) { + s->entropy_delay = (res > 1) ? (unsigned)res : 0; + trace_ot_csrng_entropy_rejected(ot_csrng_get_slot(inst), + res < 0 ? (res == -2 ? "stalled" : + "error") : + "not ready", + res); return res < 0 ? (res == -2 ? CSRNG_CMD_STALLED : CSRNG_CMD_ERROR) : CSRNG_CMD_RETRY; } @@ -679,6 +692,8 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) drng->reseed_counter = 1u; + drng->seeded = true; + return CSRNG_CMD_OK; } @@ -799,7 +814,7 @@ static bool ot_csrng_is_in_queue(OtCSRNGInstance *inst) static bool ot_csrng_expedite_uninstantiation(OtCSRNGInstance *inst) { - /* check if the instance has been flagged for uninstanciation */ + /* check if the instance has been flagged for uninstantiation */ if (ot_fifo32_is_empty(&inst->cmd_fifo)) { return false; } @@ -818,10 +833,11 @@ static bool ot_csrng_expedite_uninstantiation(OtCSRNGInstance *inst) QSIMPLEQ_REMOVE(&s->cmd_requests, inst, OtCSRNGInstance, cmd_request); if (QSIMPLEQ_EMPTY(&s->cmd_requests)) { - timer_del(s->cmd_scheduler); + qemu_bh_cancel(s->cmd_scheduler); + timer_del(s->entropy_scheduler); } - trace_ot_csrng_instanciate(slot, false); + trace_ot_csrng_instantiate(slot, false); ot_csrng_drng_uninstantiate(inst); ot_csrng_complete_command(inst, 0); @@ -835,7 +851,6 @@ static void ot_csrng_handle_enable(OtCSRNGState *s) * "CSRNG may only be enabled if ENTROPY_SRC is enabled. CSRNG may only be * disabled if all EDNs are disabled. Once disabled, CSRNG may only be * re-enabled after ENTROPY_SRC has been disabled and re-enabled." - * ... */ OtRandomSrcIfClass *cls = OT_RANDOM_SRC_IF_GET_CLASS(s->random_src); OtRandomSrcIf *randif = OT_RANDOM_SRC_IF(s->random_src); @@ -843,25 +858,26 @@ static void ot_csrng_handle_enable(OtCSRNGState *s) if (ot_csrng_is_ctrl_enabled(s)) { xtrace_ot_csrng_info("enabling CSRNG", 0); int gennum = cls->get_random_generation(randif); - /* - * ... however it is not re-enabling CSRNG w/o cycling the entropy_src - * that is prohibited, but to request entropy from it. The check is - * therefore deferred to the reseed handling which makes use of the - * entropy_src only if flag0 is not set. - */ if (gennum >= 0) { + /* + * however it is not re-enabling CSRNG w/o cycling the entropy_src + * that is prohibited, but to request entropy from it. The check is + * therefore deferred to the reseed handling which makes use of the + * entropy_src only if flag0 is not set. + */ s->es_available = gennum > s->entropy_gennum; - s->enabled = true; - s->es_retry_count = ENTROPY_SRC_INITIAL_REQUEST_COUNT; - s->entropy_gennum = gennum; - xtrace_ot_csrng_info("enable: new RS generation", gennum); + xtrace_ot_csrng_info("enable: new ES generation", gennum); } else { + /* + * tracking enablement/disablement order is not supported by the + * entropy source (such as on Darjeeling) + */ s->es_available = true; - s->enabled = true; - s->es_retry_count = ENTROPY_SRC_INITIAL_REQUEST_COUNT; - s->entropy_gennum = gennum; - xtrace_ot_csrng_info("enable: unique RS generation", gennum); + xtrace_ot_csrng_info("enable: no ES gen tracking", gennum); } + s->enabled = true; + s->es_retry_count = ENTROPY_SRC_INITIAL_REQUEST_COUNT; + s->entropy_gennum = gennum; } if (ot_csrng_is_ctrl_disabled(s)) { @@ -891,7 +907,8 @@ static void ot_csrng_handle_enable(OtCSRNGState *s) xtrace_ot_csrng_info("disable: last RS generation", s->entropy_gennum); /* cancel any outstanding asynchronous request */ - timer_del(s->cmd_scheduler); + qemu_bh_cancel(s->cmd_scheduler); + timer_del(s->entropy_scheduler); /* discard any on-going command request */ OtCSRNGInstance *inst, *next; @@ -1001,7 +1018,7 @@ ot_csrng_handle_instantiate(OtCSRNGState *s, unsigned slot) { OtCSRNGInstance *inst = &s->instances[slot]; - trace_ot_csrng_instanciate(slot, true); + trace_ot_csrng_instantiate(slot, true); uint32_t command = ot_fifo32_peek(&inst->cmd_fifo); uint32_t clen = FIELD_EX32(command, OT_CSNRG_CMD, CLEN); @@ -1025,7 +1042,7 @@ ot_csrng_handle_instantiate(OtCSRNGState *s, unsigned slot) int res; - res = ot_csrng_drng_instanciate(inst, s->random_src, flag0); + res = ot_csrng_drng_instantiate(inst, s->random_src, flag0); if ((res == CSRNG_CMD_OK) && !flag0) { /* if flag0 is set, entropy source is not used for reseeding */ s->regs[R_INTR_STATE] |= INTR_CS_ENTROPY_REQ_MASK; @@ -1040,7 +1057,7 @@ ot_csrng_handle_uninstantiate(OtCSRNGState *s, unsigned slot) { OtCSRNGInstance *inst = &s->instances[slot]; - trace_ot_csrng_instanciate(slot, false); + trace_ot_csrng_instantiate(slot, false); ot_csrng_drng_uninstantiate(inst); @@ -1176,7 +1193,15 @@ static void ot_csrng_hwapp_ready_irq(void *opaque, int n, int level) ot_csrng_drng_remaining_count(inst)); if (ready) { - qemu_bh_schedule(inst->hw.filler_bh); + if (!inst->drng.seeded) { + /* + * instanciation has not completed yet, wait for generation. + * see #ot_csrng_drng_instanciate + */ + trace_ot_csrng_defer_generation(slot); + } else { + qemu_bh_schedule(inst->hw.filler_bh); + } } } @@ -1218,8 +1243,6 @@ static void ot_csrng_hwapp_filler_bh(void *opaque) * its readiness status (only generate commands complete async.) */ if (!ot_csrng_drng_remaining_count(inst)) { - unsigned slot = ot_csrng_get_slot(inst); - xtrace_ot_csrng_info("complete deferred generation", slot); ot_csrng_complete_command(inst, 0); } } @@ -1244,8 +1267,6 @@ static void ot_csrng_swapp_fill(OtCSRNGInstance *inst) } else { /* check if the instance is running an deferred completion command */ if (inst->defer_completion) { - unsigned slot = ot_csrng_get_slot(inst); - xtrace_ot_csrng_info("complete deferred generation", slot); ot_csrng_complete_command(inst, 0); } } @@ -1368,7 +1389,9 @@ static void ot_csrng_command_schedule(OtCSRNGState *s, OtCSRNGInstance *inst) { bool queued = ot_csrng_is_in_queue(inst); if (queued) { - xtrace_ot_csrng_error("instance executing several commands at once"); + /* execution resumes, but this is likely internal bug...*/ + error_report("%s: instance executing several commands at once", + __func__); s->regs[R_INTR_STATE] |= INTR_CS_HW_INST_EXC_MASK; ot_csrng_update_irqs(s); return; @@ -1376,14 +1399,9 @@ static void ot_csrng_command_schedule(OtCSRNGState *s, OtCSRNGInstance *inst) QSIMPLEQ_INSERT_TAIL(&s->cmd_requests, inst, cmd_request); - if (timer_pending(s->cmd_scheduler)) { - xtrace_ot_csrng_info("command scheduler already active", 0); - return; - } - trace_ot_csrng_schedule(ot_csrng_get_slot(inst), "command"); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - timer_mod(s->cmd_scheduler, (int64_t)(now + CMD_EXECUTE_DELAY_NS)); + timer_del(s->entropy_scheduler); + qemu_bh_schedule(s->cmd_scheduler); } static void ot_csrng_command_scheduler(void *opaque) @@ -1464,9 +1482,15 @@ static void ot_csrng_command_scheduler(void *opaque) if (!QSIMPLEQ_EMPTY(&s->cmd_requests)) { if (s->state != CSRNG_ERROR) { - xtrace_ot_csrng_info("scheduling new command", 0); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - timer_mod(s->cmd_scheduler, (int64_t)(now + CMD_EXECUTE_DELAY_NS)); + trace_ot_csrng_scheduling_command(slot); + if (CSRNG_CMD_RETRY == res && s->entropy_delay) { + timer_mod(s->entropy_scheduler, + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + + (int64_t)s->entropy_delay); + s->entropy_delay = 0; + } else { + qemu_bh_schedule(s->cmd_scheduler); + } } else { xtrace_ot_csrng_error("cannot schedule new command on error"); } @@ -1764,11 +1788,14 @@ static void ot_csrng_reset(DeviceState *dev) { OtCSRNGState *s = OT_CSRNG(dev); + trace_ot_csrng_reset(); + g_assert(s->random_src); OBJECT_CHECK(OtRandomSrcIf, s->random_src, TYPE_OT_RANDOM_SRC_IF); g_assert(s->otp_ctrl); - timer_del(s->cmd_scheduler); + timer_del(s->entropy_scheduler); + s->entropy_delay = 0; memset(s->regs, 0, REGS_SIZE); @@ -1816,7 +1843,7 @@ static void ot_csrng_init(Object *obj) /* aes_desc is defined in libtomcrypt */ s->aes_cipher = register_cipher(&aes_desc); if (s->aes_cipher < 0) { - error_report("OpenTitan AES: Unable to use libtomcrypt AES API"); + error_report("%s: unable to use libtomcrypt AES API", __func__); } s->regs = g_new0(uint32_t, REGS_COUNT); @@ -1845,8 +1872,9 @@ static void ot_csrng_init(Object *obj) /* current instance is the SW instance */ ot_fifo32_create(&inst->sw.bits_fifo, OT_CSRNG_PACKET_WORD_COUNT); - s->cmd_scheduler = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_csrng_command_scheduler, s); + s->cmd_scheduler = qemu_bh_new(&ot_csrng_command_scheduler, s); + s->entropy_scheduler = + timer_new_ns(OT_VIRTUAL_CLOCK, &ot_csrng_command_scheduler, s); QSIMPLEQ_INIT(&s->cmd_requests); } diff --git a/hw/opentitan/ot_dev_proxy.c b/hw/opentitan/ot_dev_proxy.c index ab8b0eba63cb..39dd5060d389 100644 --- a/hw/opentitan/ot_dev_proxy.c +++ b/hw/opentitan/ot_dev_proxy.c @@ -47,6 +47,7 @@ #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" +#include "sysemu/runstate.h" #include "trace.h" /* ------------------------------------------------------------------------ */ @@ -317,8 +318,8 @@ static void ot_dev_proxy_enumerate_devices(OtDevProxyState *s) memcpy(&entry->desc[2u], item->caps.mr->name, slen); entry->desc[2u + slen] = (char)('0' + mrcount++); } else { - qemu_log("ignoring discovered device: %s\n", - object_get_typename(item->obj)); + warn_report("%s: ignoring discovered device: %s\n", __func__, + object_get_typename(item->obj)); continue; } entry->header = ix << 16u; @@ -1183,7 +1184,7 @@ static void ot_dev_proxy_quit(OtDevProxyState *s) ot_dev_proxy_reply_payload(s, PROXY_COMMAND('q', 't'), NULL, 0); usleep(200000); - exit(code); + qemu_system_shutdown_request_with_code(SHUTDOWN_CAUSE_GUEST_SHUTDOWN, code); } static void ot_dev_proxy_intercepted_irq(void *opaque, int irq, int level) @@ -1301,7 +1302,7 @@ static void ot_dev_proxy_receive(void *opaque, const uint8_t *buf, int size) OtDevProxyState *s = opaque; if (fifo8_num_free(&s->rx_fifo) < size) { - qemu_log("Incoherent chardev receive\n"); + error_report("%s: Unexpected chardev receive\n", __func__); return; } diff --git a/hw/opentitan/ot_dm_tl.c b/hw/opentitan/ot_dm_tl.c index 9590b4a62cb3..713ea9dd0ca2 100644 --- a/hw/opentitan/ot_dm_tl.c +++ b/hw/opentitan/ot_dm_tl.c @@ -38,7 +38,7 @@ #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/debug.h" -#include "hw/riscv/dmi.h" +#include "hw/riscv/dtm.h" #include "hw/riscv/ibex_common.h" #include "hw/sysbus.h" #include "trace.h" @@ -50,9 +50,9 @@ struct OtDMTLState { hwaddr tl_offset; uint32_t value; MemTxAttrs attrs; - bool dmi_ok; /* DMI is available */ + bool dtm_ok; /* DTM is available */ - RISCVDMIState *dmi; + RISCVDTMState *dtm; SysBusDevice *tl_dev; char *tl_as_name; uint64_t tl_base; @@ -62,7 +62,7 @@ struct OtDMTLState { }; /* -------------------------------------------------------------------------- */ -/* DMI interface implementation */ +/* DTM interface implementation */ /* -------------------------------------------------------------------------- */ static RISCVDebugResult @@ -124,7 +124,7 @@ static uint32_t ot_dm_tl_read_value(RISCVDebugDeviceState *dev) } static Property ot_dm_tl_properties[] = { - DEFINE_PROP_LINK("dmi", OtDMTLState, dmi, TYPE_RISCV_DMI, RISCVDMIState *), + DEFINE_PROP_LINK("dtm", OtDMTLState, dtm, TYPE_RISCV_DTM, RISCVDTMState *), DEFINE_PROP_UINT32("dmi_addr", OtDMTLState, dmi_addr, 0), DEFINE_PROP_UINT32("dmi_size", OtDMTLState, dmi_size, 0), DEFINE_PROP_STRING("tl_as_name", OtDMTLState, tl_as_name), @@ -139,14 +139,14 @@ static void ot_dm_tl_reset(DeviceState *dev) { OtDMTLState *dmtl = OT_DM_TL(dev); - g_assert(dmtl->dmi != NULL); + g_assert(dmtl->dtm != NULL); g_assert(dmtl->dmi_size); - dmtl->dmi_ok = - riscv_dmi_register_dm(DEVICE(dmtl->dmi), RISCV_DEBUG_DEVICE(dev), + dmtl->dtm_ok = + riscv_dtm_register_dm(DEVICE(dmtl->dtm), RISCV_DEBUG_DEVICE(dev), dmtl->dmi_addr, dmtl->dmi_size); - if (dmtl->dmi_ok) { + if (dmtl->dtm_ok) { Object *soc = OBJECT(dev)->parent; Object *obj; OtAddressSpaceState *oas; diff --git a/hw/opentitan/ot_dma.c b/hw/opentitan/ot_dma.c index 3b52211f501c..aaf7e92c5f78 100644 --- a/hw/opentitan/ot_dma.c +++ b/hw/opentitan/ot_dma.c @@ -880,7 +880,7 @@ static bool ot_dma_go(OtDMAState *s) s->regs[R_STATUS] |= R_STATUS_BUSY_MASK; timer_del(s->timer); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->timer, (int64_t)(now + DMA_PACE_NS)); return true; @@ -899,7 +899,7 @@ static void ot_dma_abort(OtDMAState *s) /* simulate a delayed response */ timer_del(s->timer); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->timer, (int64_t)(now + DMA_PACE_NS)); } @@ -1014,7 +1014,7 @@ static void ot_dma_transfer(void *opaque) if (op->size) { /* schedule next block if any */ - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->timer, (int64_t)(now + DMA_PACE_NS)); return; } @@ -1345,7 +1345,7 @@ static void ot_dma_init(Object *obj) ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); } - s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_dma_transfer, s); + s->timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_dma_transfer, s); } static void ot_dma_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_edn.c b/hw/opentitan/ot_edn.c index a3d04fb8ac5b..b7bfe02f77e2 100644 --- a/hw/opentitan/ot_edn.c +++ b/hw/opentitan/ot_edn.c @@ -45,6 +45,7 @@ #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" #include "hw/sysbus.h" +#include "sysemu/runstate.h" #include "trace.h" @@ -821,7 +822,7 @@ static void ot_edn_dispatch(OtEDNState *s) } } -static void ot_edn_clean_up(OtEDNState *s) +static void ot_edn_clean_up(OtEDNState *s, bool discard_requests) { OtEDNCSRNG *c = &s->rng; @@ -836,12 +837,14 @@ static void ot_edn_clean_up(OtEDNState *s) for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { ibex_irq_set(&s->alerts[ix], 0); } -#ifdef EDN_DISCARD_PENDING_REQUEST_ON_DISABLE - /* clear all pending end point requests */ - while (QSIMPLEQ_FIRST(&s->ep_requests)) { - QSIMPLEQ_REMOVE_HEAD(&s->ep_requests, request); + + if (discard_requests) { + /* clear all pending end point requests */ + while (QSIMPLEQ_FIRST(&s->ep_requests)) { + QSIMPLEQ_REMOVE_HEAD(&s->ep_requests, request); + } } -#endif + for (unsigned epix = 0; epix < ARRAY_SIZE(s->endpoints); epix++) { ot_fifo32_reset(&s->endpoints[epix].fifo); s->endpoints[epix].fips = false; @@ -865,7 +868,7 @@ static void ot_edn_fill_bits(void *opaque, const uint32_t *bits, bool fips) default: xtrace_ot_edn_error(c->appid, "unexpected state"); ot_edn_change_state(s, EDN_ERROR); - exit(1); + qemu_system_shutdown_request_with_code(SHUTDOWN_CAUSE_GUEST_PANIC, 1); break; } @@ -1000,7 +1003,11 @@ static void ot_edn_csrng_ack_irq(void *opaque, int n, int level) if (ot_edn_is_sw_port_mode(s)) { ot_edn_complete_sw_req(s); } - ot_edn_clean_up(s); +#ifdef EDN_DISCARD_PENDING_REQUEST_ON_DISABLE + ot_edn_clean_up(s, true); +#else + ot_edn_clean_up(s, false); +#endif return; default: break; @@ -1273,13 +1280,15 @@ static void ot_edn_reset(DeviceState *dev) OtEDNState *s = OT_EDN(dev); OtEDNCSRNG *c = &s->rng; + trace_ot_edn_reset(s->rng.appid); + memset(s->regs, 0, REGS_SIZE); s->regs[R_REGWEN] = 0x1u; s->regs[R_CTRL] = 0x9999u; s->regs[R_BOOT_INS_CMD] = 0x901u; s->regs[R_BOOT_GEN_CMD] = 0xfff003u; - ot_edn_clean_up(s); + ot_edn_clean_up(s, true); /* do not reset connection info since reset order is not known */ (void)c->genbits_ready; diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index ed59fd9eaf7a..de069e9302f7 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -502,9 +502,20 @@ static int ot_entropy_src_get_random(OtRandomSrcIf *dev, int genid, case ENTROPY_SRC_STARTUP_HT_START: case ENTROPY_SRC_STARTUP_PHASE1: case ENTROPY_SRC_STARTUP_PASS1: - case ENTROPY_SRC_STARTUP_FAIL1: - trace_ot_entropy_src_init_ongoing(STATE_NAME(s->state), s->state); - return 1; /* not ready */ + case ENTROPY_SRC_STARTUP_FAIL1: { + int wait_ns; + if (timer_pending(s->scheduler)) { + wait_ns = 1; + } else { + /* computed delay fits into a 31-bit value */ + wait_ns = (int)(timer_expire_time_ns(s->scheduler) - + qemu_clock_get_ns(OT_VIRTUAL_CLOCK)); + } + trace_ot_entropy_src_init_ongoing(STATE_NAME(s->state), s->state, + wait_ns); + /* not ready */ + return wait_ns; + } case ENTROPY_SRC_IDLE: qemu_log_mask(LOG_GUEST_ERROR, "%s: module is not enabled\n", __func__); return -1; @@ -766,7 +777,7 @@ static void ot_entropy_src_update_filler(OtEntropySrcState *s) */ if (!timer_pending(s->scheduler)) { trace_ot_entropy_src_info("reschedule"); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->scheduler, (int64_t)(now + (uint64_t)ES_FILL_RATE_NS)); } } @@ -1320,7 +1331,7 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, /* boot phase */ ot_entropy_src_change_state(s, ENTROPY_SRC_BOOT_HT_RUNNING); } - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->scheduler, (int64_t)(now + (uint64_t)OT_ENTROPY_SRC_BOOT_DELAY_NS)); @@ -1533,6 +1544,8 @@ static void ot_entropy_src_reset(DeviceState *dev) { OtEntropySrcState *s = OT_ENTROPY_SRC(dev); + trace_ot_entropy_src_reset(); + g_assert(s->ast); g_assert(s->otp_ctrl); @@ -1618,8 +1631,7 @@ static void ot_entropy_src_init(Object *obj) ot_fifo32_create(&s->swread_fifo, ES_SWREAD_FIFO_WORD_COUNT); ot_fifo32_create(&s->final_fifo, ES_FINAL_FIFO_WORD_COUNT); - s->scheduler = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_entropy_src_scheduler, s); + s->scheduler = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_entropy_src_scheduler, s); } static void ot_entropy_src_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_flash.c b/hw/opentitan/ot_flash.c index c320a16c5643..f52cfdc22882 100644 --- a/hw/opentitan/ot_flash.c +++ b/hw/opentitan/ot_flash.c @@ -52,9 +52,6 @@ #include "sysemu/block-backend.h" #include "trace.h" -/* set to abort QEMU whenever guest code disable flash access */ -#define ABORT_ON_DISABLEMENT 1 - /* set to use I/O to access the flash partition */ #define DATA_PART_USE_IO_OPS 0 @@ -672,7 +669,7 @@ struct OtFlashState { static void ot_flash_update_irqs(OtFlashState *s) { uint32_t level = s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE]; - trace_ot_csrng_irqs(s->regs[R_INTR_STATE], s->regs[R_INTR_ENABLE], level); + trace_ot_flash_irqs(s->regs[R_INTR_STATE], s->regs[R_INTR_ENABLE], level); for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { ibex_irq_set(&s->irqs[ix], (int)((level >> ix) & 0x1u)); } @@ -724,7 +721,7 @@ static void ot_flash_initialize(OtFlashState *s) s->regs[R_PHY_STATUS] = FIELD_DP32(s->regs[R_PHY_STATUS], PHY_STATUS, INIT_WIP, 0u); timer_mod(s->op_delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + OP_INIT_DURATION_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + OP_INIT_DURATION_NS); } static bool ot_flash_fifo_in_reset(OtFlashState *s) @@ -1059,14 +1056,10 @@ static void ot_flash_regs_write(void *opaque, hwaddr addr, uint64_t val64, val32 &= R_DIS_VAL_MASK; s->regs[reg] = ot_multibitbool_w1s_write(s->regs[reg], val32, 4u); if (ot_flash_is_disabled(s)) { -#if ABORT_ON_DISABLEMENT - error_setg(&error_fatal, "flash controller disabled by SW"); -#else xtrace_ot_flash_error("flash controller disabled by SW"); memory_region_set_enabled(&s->mmio.mem, false); memory_region_set_enabled(&s->mmio.csrs, false); memory_region_set_enabled(&s->mmio.regs, false); -#endif } break; case R_INIT: @@ -1831,7 +1824,7 @@ static void ot_flash_init(Object *obj) for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); } - s->op_delay = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_flash_op_signal, s); + s->op_delay = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_flash_op_signal, s); } static void ot_flash_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_gpio.c b/hw/opentitan/ot_gpio.c index fd119c0b0393..1992f6e744b5 100644 --- a/hw/opentitan/ot_gpio.c +++ b/hw/opentitan/ot_gpio.c @@ -358,7 +358,7 @@ static void ot_gpio_chr_receive(void *opaque, const uint8_t *buf, int size) OtGpioState *s = opaque; if (s->ipos + (unsigned)size > sizeof(s->ibuf)) { - qemu_log("%s: Incoherent chardev receive\n", __func__); + error_report("%s: Unexpected chardev receive\n", __func__); return; } diff --git a/hw/opentitan/ot_hmac.c b/hw/opentitan/ot_hmac.c index 32e788179cfc..96429738367a 100644 --- a/hw/opentitan/ot_hmac.c +++ b/hw/opentitan/ot_hmac.c @@ -34,6 +34,7 @@ #include "hw/irq.h" #include "hw/opentitan/ot_alert.h" #include "hw/opentitan/ot_clkmgr.h" +#include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_hmac.h" #include "hw/qdev-properties-system.h" #include "hw/qdev-properties.h" @@ -465,7 +466,7 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value, timer_del(s->fifo_trigger_handle); ibex_irq_set(&s->clkmgr, true); timer_mod(s->fifo_trigger_handle, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + FIFO_TRIGGER_DELAY_NS); } break; @@ -566,7 +567,7 @@ static void ot_hmac_fifo_write(void *opaque, hwaddr addr, uint64_t value, /* trigger delayed processing of FIFO */ timer_del(s->fifo_trigger_handle); timer_mod(s->fifo_trigger_handle, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + FIFO_TRIGGER_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + FIFO_TRIGGER_DELAY_NS); } static Property ot_hmac_properties[] = { @@ -619,7 +620,7 @@ static void ot_hmac_init(Object *obj) /* setup FIFO Interrupt Timer */ s->fifo_trigger_handle = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_hmac_fifo_trigger_update, s); + timer_new_ns(OT_VIRTUAL_CLOCK, &ot_hmac_fifo_trigger_update, s); /* FIFO sizes as per OT Spec */ fifo8_create(&s->input_fifo, OT_HMAC_FIFO_LENGTH); diff --git a/hw/opentitan/ot_ibex_wrapper_dj.c b/hw/opentitan/ot_ibex_wrapper_dj.c index 0544cc7ff3b3..f507ff49af11 100644 --- a/hw/opentitan/ot_ibex_wrapper_dj.c +++ b/hw/opentitan/ot_ibex_wrapper_dj.c @@ -42,6 +42,7 @@ #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" #include "hw/sysbus.h" +#include "sysemu/runstate.h" #include "trace.h" @@ -709,12 +710,14 @@ struct OtIbexWrapperDjState { uint32_t *regs; OtIbexTestLogEngine *log_engine; + CPUState *cpu; uint8_t cpu_en_bm; bool entropy_requested; bool edn_connected; /* Optional properties */ char *ot_id; + char *lc_ignore_ids; OtEDNState *edn; uint8_t edn_ep; bool lc_ignore; @@ -1267,24 +1270,16 @@ static void ot_ibex_wrapper_dj_cpu_enable_recv(void *opaque, int n, int level) trace_ot_ibex_wrapper_cpu_enable(s->ot_id ?: "", n ? "PWR" : "LC", (bool)level, s->cpu_en_bm, enable); - CPUState *cpu = ot_common_get_local_cpu(DEVICE(s)); - if (!cpu) { - error_setg(&error_fatal, "Could not find the vCPU to start!"); - g_assert_not_reached(); - } - - bool in_reset = cpu->held_in_reset; - if (enable) { - cpu->halted = 0; - if (in_reset) { - resettable_release_reset(OBJECT(cpu), RESET_TYPE_COLD); + s->cpu->halted = 0; + if (s->cpu->held_in_reset) { + resettable_release_reset(OBJECT(s->cpu), RESET_TYPE_COLD); } - cpu_resume(cpu); + cpu_resume(s->cpu); } else { - if (!cpu->halted) { - cpu->halted = 1; - cpu_loop_exit(cpu); + if (!s->cpu->halted) { + s->cpu->halted = 1; + cpu_exit(s->cpu); } } } @@ -1377,7 +1372,8 @@ static void ot_ibex_wrapper_dj_regs_write(void *opaque, hwaddr addr, if (val32 > 127u) { val32 = 127u; } - exit((int)val32); + qemu_system_shutdown_request_with_code( + SHUTDOWN_CAUSE_GUEST_SHUTDOWN, (int)val32); } val32 &= R_SW_FATAL_ERR_VAL_MASK; s->regs[reg] = ot_multibitbool_w1s_write(s->regs[reg], val32, 4u); @@ -1429,7 +1425,8 @@ static void ot_ibex_wrapper_dj_regs_write(void *opaque, hwaddr addr, switch (val32 & R_DV_SIM_STATUS_CODE_MASK) { case TEST_STATUS_PASSED: trace_ot_ibex_wrapper_exit(s->ot_id, "DV SIM success, exiting", 0); - exit(0); + qemu_system_shutdown_request_with_code( + SHUTDOWN_CAUSE_GUEST_SHUTDOWN, 0); break; case TEST_STATUS_FAILED: { uint32_t info = FIELD_EX32(val32, DV_SIM_STATUS, INFO); @@ -1442,7 +1439,8 @@ static void ot_ibex_wrapper_dj_regs_write(void *opaque, hwaddr addr, } trace_ot_ibex_wrapper_exit(s->ot_id, "DV SIM failure, exiting", ret); - exit(ret); + qemu_system_shutdown_request_with_code( + SHUTDOWN_CAUSE_GUEST_SHUTDOWN, ret); break; } default: @@ -1466,6 +1464,7 @@ static Property ot_ibex_wrapper_dj_properties[] = { OtEDNState *), DEFINE_PROP_UINT8("edn-ep", OtIbexWrapperDjState, edn_ep, UINT8_MAX), DEFINE_PROP_BOOL("lc-ignore", OtIbexWrapperDjState, lc_ignore, false), + DEFINE_PROP_STRING("lc-ignore-ids", OtIbexWrapperDjState, lc_ignore_ids), DEFINE_PROP_CHR("logdev", OtIbexWrapperDjState, chr), DEFINE_PROP_END_OF_LIST(), }; @@ -1482,12 +1481,32 @@ static void ot_ibex_wrapper_dj_reset(DeviceState *dev) { OtIbexWrapperDjState *s = OT_IBEX_WRAPPER_DJ(dev); - g_assert(s->ot_id); - trace_ot_ibex_wrapper_reset(s->ot_id); + g_assert(s->ot_id); g_assert(s->sys_mem); + if (s->lc_ignore_ids) { + char *ign = g_strdup(s->lc_ignore_ids); + char *token = strtok(ign, ","); + while (token) { + if (!strcmp(token, s->ot_id)) { + s->lc_ignore = true; + } + token = strtok(NULL, ","); + } + g_free(ign); + } + + if (!s->cpu) { + CPUState *cpu = ot_common_get_local_cpu(DEVICE(s)); + if (!cpu) { + error_setg(&error_fatal, "Could not find the associated vCPU"); + g_assert_not_reached(); + } + s->cpu = cpu; + } + for (unsigned slot = 0; slot < PARAM_NUM_REGIONS; slot++) { ot_ibex_wrapper_dj_remapper_destroy(s, slot); } diff --git a/hw/opentitan/ot_ibex_wrapper_eg.c b/hw/opentitan/ot_ibex_wrapper_eg.c index 55febe22c834..7122e672c090 100644 --- a/hw/opentitan/ot_ibex_wrapper_eg.c +++ b/hw/opentitan/ot_ibex_wrapper_eg.c @@ -43,6 +43,7 @@ #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" #include "hw/sysbus.h" +#include "sysemu/runstate.h" #include "trace.h" @@ -228,6 +229,7 @@ struct OtIbexWrapperEgState { uint32_t *regs; OtIbexTestLogEngine *log_engine; + CPUState *cpu; uint8_t cpu_en_bm; bool entropy_requested; bool edn_connected; @@ -726,24 +728,16 @@ static void ot_ibex_wrapper_eg_cpu_enable_recv(void *opaque, int n, int level) trace_ot_ibex_wrapper_cpu_enable(s->ot_id ?: "", n ? "PWR" : "LC", (bool)level, s->cpu_en_bm, enable); - CPUState *cpu = ot_common_get_local_cpu(DEVICE(s)); - if (!cpu) { - error_setg(&error_fatal, "Could not find the vCPU to start!"); - g_assert_not_reached(); - } - - bool in_reset = cpu->held_in_reset; - if (enable) { - cpu->halted = 0; - if (in_reset) { - resettable_release_reset(OBJECT(cpu), RESET_TYPE_COLD); + s->cpu->halted = 0; + if (s->cpu->held_in_reset) { + resettable_release_reset(OBJECT(s->cpu), RESET_TYPE_COLD); } - cpu_resume(cpu); + cpu_resume(s->cpu); } else { - if (!cpu->halted) { - cpu->halted = 1; - cpu_loop_exit(cpu); + if (!s->cpu->halted) { + s->cpu->halted = 1; + cpu_exit(s->cpu); } } } @@ -824,7 +818,8 @@ static void ot_ibex_wrapper_eg_regs_write(void *opaque, hwaddr addr, if (val32 > 127u) { val32 = 127u; } - exit((int)val32); + qemu_system_shutdown_request_with_code( + SHUTDOWN_CAUSE_GUEST_SHUTDOWN, (int)val32); } val32 &= R_SW_FATAL_ERR_VAL_MASK; s->regs[reg] = ot_multibitbool_w1s_write(s->regs[reg], val32, 4u); @@ -884,7 +879,8 @@ static void ot_ibex_wrapper_eg_regs_write(void *opaque, hwaddr addr, switch (val32) { case TEST_STATUS_PASSED: trace_ot_ibex_wrapper_exit(s->ot_id, "DV SIM success, exiting", 0); - exit(0); + qemu_system_shutdown_request_with_code( + SHUTDOWN_CAUSE_GUEST_SHUTDOWN, 0); break; case TEST_STATUS_FAILED: { uint32_t info = FIELD_EX32(val32, DV_SIM_STATUS, INFO); @@ -897,7 +893,8 @@ static void ot_ibex_wrapper_eg_regs_write(void *opaque, hwaddr addr, } trace_ot_ibex_wrapper_exit(s->ot_id, "DV SIM failure, exiting", ret); - exit(ret); + qemu_system_shutdown_request_with_code( + SHUTDOWN_CAUSE_GUEST_SHUTDOWN, ret); break; } default: @@ -935,12 +932,21 @@ static void ot_ibex_wrapper_eg_reset(DeviceState *dev) { OtIbexWrapperEgState *s = OT_IBEX_WRAPPER_EG(dev); - g_assert(s->ot_id); trace_ot_ibex_wrapper_reset(s->ot_id); + g_assert(s->ot_id); g_assert(s->edn); g_assert(s->edn_ep != UINT8_MAX); + if (!s->cpu) { + CPUState *cpu = ot_common_get_local_cpu(DEVICE(s)); + if (!cpu) { + error_setg(&error_fatal, "Could not find the associated vCPU"); + g_assert_not_reached(); + } + s->cpu = cpu; + } + for (unsigned slot = 0; slot < PARAM_NUM_REGIONS; slot++) { ot_ibex_wrapper_eg_remapper_destroy(s, slot); } diff --git a/hw/opentitan/ot_kmac.c b/hw/opentitan/ot_kmac.c index da2319fff50e..dd9df18e0b88 100644 --- a/hw/opentitan/ot_kmac.c +++ b/hw/opentitan/ot_kmac.c @@ -441,7 +441,7 @@ static void ot_kmac_trigger_deferred_bh(OtKMACState *s) { timer_del(s->bh_timer); timer_mod(s->bh_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + BH_TRIGGER_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + BH_TRIGGER_DELAY_NS); } static void ot_kmac_bh_timer_handler(void *opaque) @@ -1649,8 +1649,7 @@ static void ot_kmac_init(Object *obj) &s->msgfifo_mmio); /* setup deferred processing */ - s->bh_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_kmac_bh_timer_handler, s); + s->bh_timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_kmac_bh_timer_handler, s); s->bh = qemu_bh_new(&ot_kmac_process, s); /* FIFO sizes as per OT Spec */ diff --git a/hw/opentitan/ot_otbn.c b/hw/opentitan/ot_otbn.c index 0e749e06cacb..d56e82efa806 100644 --- a/hw/opentitan/ot_otbn.c +++ b/hw/opentitan/ot_otbn.c @@ -38,6 +38,7 @@ #include "qapi/error.h" #include "hw/opentitan/ot_alert.h" #include "hw/opentitan/ot_clkmgr.h" +#include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_edn.h" #include "hw/opentitan/ot_fifo32.h" #include "hw/opentitan/ot_otbn.h" @@ -253,7 +254,7 @@ static void ot_otbn_proxy_completion_bh(void *opaque) */ timer_del(s->proxy_defer); timer_mod(s->proxy_defer, - qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 100u); + qemu_clock_get_us(OT_VIRTUAL_CLOCK) + 100u); } else { ot_otbn_post_execute(s); } @@ -676,7 +677,7 @@ static void ot_otbn_init(Object *obj) } s->proxy_completion_bh = qemu_bh_new(&ot_otbn_proxy_completion_bh, s); - s->proxy_defer = timer_new_us(QEMU_CLOCK_VIRTUAL, &ot_otbn_post_execute, s); + s->proxy_defer = timer_new_us(OT_VIRTUAL_CLOCK, &ot_otbn_post_execute, s); s->proxy = ot_otbn_proxy_new(&ot_otbn_trigger_entropy_req, &s->rnds[OT_OTBN_URND], &ot_otbn_trigger_entropy_req, &s->rnds[OT_OTBN_RND], diff --git a/hw/opentitan/ot_otp_dj.c b/hw/opentitan/ot_otp_dj.c index dec1c33f3266..86684e8b4c3e 100644 --- a/hw/opentitan/ot_otp_dj.c +++ b/hw/opentitan/ot_otp_dj.c @@ -1671,7 +1671,7 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) if (!ot_otp_dj_is_buffered(partition)) { /* fake slow access to OTP cell */ timer_mod(s->dai.delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + DAI_READ_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_READ_DELAY_NS); } else { DAI_CHANGE_STATE(s, OTP_DAI_IDLE); } @@ -1785,7 +1785,7 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s) DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT); timer_mod(s->dai.delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + DAI_WRITE_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_WRITE_DELAY_NS); } static void ot_otp_dj_dai_digest(OtOTPDjState *s) @@ -1866,7 +1866,7 @@ static void ot_otp_dj_dai_digest(OtOTPDjState *s) /* fake slow access to OTP cell */ timer_mod(s->dai.delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + DAI_DIGEST_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_DIGEST_DELAY_NS); } static void ot_otp_dj_dai_write_digest(void *opaque) @@ -1897,7 +1897,7 @@ static void ot_otp_dj_dai_write_digest(void *opaque) DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT); timer_mod(s->dai.delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + DAI_WRITE_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_WRITE_DELAY_NS); } else { /* TODO: no idea on how to report the error since partition is undef */ ot_otp_dj_dai_set_error(s, error); @@ -2977,7 +2977,7 @@ static void ot_otp_dj_lci_write_word(void *opaque) lci->hpos += 1; timer_mod(lci->prog_delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + LCI_PROG_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + LCI_PROG_DELAY_NS); LCI_CHANGE_STATE(s, OTP_LCI_WRITE_WAIT); } @@ -3278,10 +3278,10 @@ static void ot_otp_dj_init(Object *obj) s->hw_cfg = g_new0(OtOTPHWCfg, 1u); s->tokens = g_new0(OtOTPTokens, 1u); - s->dai.delay = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_otp_dj_dai_complete, s); + s->dai.delay = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_dj_dai_complete, s); s->dai.digest_bh = qemu_bh_new(&ot_otp_dj_dai_write_digest, s); s->lci.prog_delay = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_otp_dj_lci_write_word, s); + timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_dj_lci_write_word, s); s->lci.prog_bh = qemu_bh_new(&ot_otp_dj_lci_write_word, s); } diff --git a/hw/opentitan/ot_otp_eg.c b/hw/opentitan/ot_otp_eg.c index 5553907a278d..ba74dcddd2a0 100644 --- a/hw/opentitan/ot_otp_eg.c +++ b/hw/opentitan/ot_otp_eg.c @@ -677,7 +677,7 @@ static void ot_otp_eg_direct_read(OtOTPEgState *s) if (!ot_otp_eg_is_buffered(partition)) { timer_mod(s->dai_delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + DAI_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_DELAY_NS); return; } @@ -1384,7 +1384,7 @@ static void ot_otp_eg_init(Object *obj) s->hw_cfg = g_new0(OtOTPHWCfg, 1u); s->entropy_cfg = g_new0(OtOTPEntropyCfg, 1u); - s->dai_delay = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_otp_eg_complete_dai, s); + s->dai_delay = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_eg_complete_dai, s); } static void ot_otp_eg_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_pwrmgr.c b/hw/opentitan/ot_pwrmgr.c index b556af8bbc82..6f5a28ba049e 100644 --- a/hw/opentitan/ot_pwrmgr.c +++ b/hw/opentitan/ot_pwrmgr.c @@ -119,6 +119,9 @@ REG32(FAULT_STATUS, 0x40u) #define CDC_SYNC_PULSE_DURATION_NS 100000u /* 100us */ +#define PWRMGR_WAKEUP_MAX 6u +#define PWRMGR_RESET_MAX 3u + /* Verbatim definitions from RTL */ #define NUM_SW_RST_REQ 1u #define HW_RESET_WIDTH \ @@ -156,10 +159,6 @@ static const char *REG_NAMES[REGS_COUNT] = { }; #undef REG_NAME_ENTRY -/* not a real register, but a way to store incoming signals */ -SHARED_FIELD(INPUTS_LC, 0u, 1u) -SHARED_FIELD(INPUTS_OTP, 1u, 1u) - typedef enum { OT_PWRMGR_INIT_OTP, OT_PWRMGR_INIT_LC_CTRL, @@ -209,15 +208,32 @@ typedef struct { } OtPwrMgrRomStatus; typedef enum { + OT_PWRMGR_NO_DOMAIN, OT_PWRMGR_SLOW_DOMAIN, OT_PWRMGR_FAST_DOMAIN, } OtPwrMgrClockDomain; typedef struct { - OtRstMgrResetReq req; OtPwrMgrClockDomain domain; + int req; } OtPwrMgrResetReq; +typedef union { + uint32_t bitmap; + struct { + uint8_t hw_reset : 1; /* HW reset request */ + uint8_t sw_reset : 1; /* SW reset request */ + uint8_t otp_done : 1; + uint8_t lc_done : 1; + uint8_t holdon_fetch : 1; /* custom extension */ + uint8_t rom_good; /* up to 8 ROMs */ + uint8_t rom_done; /* up to 8 ROMs */ + }; +} OtPwrMgrEvents; + +static_assert(sizeof(OtPwrMgrEvents) == sizeof(uint32_t), + "Invalid OtPwrMgrEvents definition"); + struct OtPwrMgrState { SysBusDevice parent_obj; @@ -232,16 +248,21 @@ struct OtPwrMgrState { OtPwrMgrFastState f_state; OtPwrMgrSlowState s_state; - unsigned fsm_event_count; - uint32_t inputs; + OtPwrMgrEvents fsm_events; uint32_t *regs; OtPwrMgrResetReq reset_req; - OtPwrMgrRomStatus *roms; char *ot_id; OtRstMgrState *rstmgr; uint8_t num_rom; + uint8_t version; + bool fetch_ctrl; +}; + +struct OtPwrMgrClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; }; #define PWRMGR_NAME_ENTRY(_pre_, _name_) [_pre_##_##_name_] = stringify(_name_) @@ -295,31 +316,77 @@ static const char *SLOW_ST_NAMES[] = { #define SST_NAME(_st_) \ ((_st_) < ARRAY_SIZE(SLOW_ST_NAMES) ? SLOW_ST_NAMES[(_st_)] : "?") -#define WAKEUP_NAME_ENTRY(_name_) PWRMGR_NAME_ENTRY(OT_PWRMGR_WAKEUP, _name_) +typedef struct { + unsigned wakeup_count; + unsigned reset_count; +} OtPwrMgrConfig; + /* clang-format off */ -static const char *WAKEUP_NAMES[] = { - WAKEUP_NAME_ENTRY(SYSRST), - WAKEUP_NAME_ENTRY(ADC_CTRL), - WAKEUP_NAME_ENTRY(PINMUX), - WAKEUP_NAME_ENTRY(USBDEV), - WAKEUP_NAME_ENTRY(AON_TIMER), - WAKEUP_NAME_ENTRY(SENSOR), +static const OtPwrMgrConfig PWRMGR_CONFIG[OT_PWMGR_VERSION_COUNT] = { + [OT_PWMGR_VERSION_EG] = { + .wakeup_count = 6u, + .reset_count = 3u, + }, + [OT_PWMGR_VERSION_DJ] = { + .wakeup_count = 6u, + .reset_count = 2u, + }, }; -/* clang-format on */ -#undef WAKEUP_NAME_ENTRY -#define WAKEUP_NAME(_clk_) \ - ((_clk_) < ARRAY_SIZE(WAKEUP_NAMES) ? WAKEUP_NAMES[(_clk_)] : "?") -#define RESET_NAME_ENTRY(_name_) PWRMGR_NAME_ENTRY(OT_PWRMGR_RST, _name_) -/* clang-format off */ -static const char *RST_NAMES[] = { - RESET_NAME_ENTRY(SYSRST), - RESET_NAME_ENTRY(AON_TIMER), +static int PWRMGR_RESET_DISPATCH[OT_PWMGR_VERSION_COUNT][PWRMGR_RESET_MAX] = { + [OT_PWMGR_VERSION_EG] = { + [0] = OT_RSTMGR_RESET_SYSCTRL, + [1] = OT_RSTMGR_RESET_AON_TIMER, + [2] = -1 + }, + [OT_PWMGR_VERSION_DJ] = { + [0] = OT_RSTMGR_RESET_AON_TIMER, + [1] = -1, + [2] = -1, + }, +}; + +static const char * +PWRMGR_WAKEUP_NAMES[OT_PWMGR_VERSION_COUNT][PWRMGR_WAKEUP_MAX] = { + [OT_PWMGR_VERSION_EG] = { + [0] = "SYSRST", + [1] = "ADC_CTRL", + [2] = "PINMUX", + [3] = "USBDEV", + [4] = "AON_TIMER", + [5] = "SENSOR", + }, + [OT_PWMGR_VERSION_DJ] = { + [0] = "PINMUX", + [1] = "USBDEV", + [2] = "AON_TIMER", + [3] = "SENSOR", + [4] = "SOC_PROXY_INT", + [5] = "SOC_PROXY_EXT", + }, +}; + +static const char *PWRMGR_RST_NAMES[OT_PWMGR_VERSION_COUNT][PWRMGR_RESET_MAX] = { + [OT_PWMGR_VERSION_EG] = { + [0] = "SYSRST", + [1] = "AON_TIMER", + [2] = "SENSOR", + }, + [OT_PWMGR_VERSION_DJ] = { + [0] = "AON_TIMER", + [1] = "SOC_PROXY", + } }; /* clang-format on */ -#undef RESET_NAME_ENTRY -#define RST_NAME(_clk_) \ - ((_clk_) < ARRAY_SIZE(RST_NAMES) ? RST_NAMES[(_clk_)] : "?") + +#define WAKEUP_NAME(_s_, _w_) \ + ((_w_) < PWRMGR_CONFIG[(_s_)->version].wakeup_count ? \ + PWRMGR_WAKEUP_NAMES[(_s_)->version][(_w_)] : \ + "?") +#define RST_NAME(_s_, _r_) \ + ((_r_) < PWRMGR_CONFIG[(_s_)->version].reset_count ? \ + PWRMGR_RST_NAMES[(_s_)->version][(_r_)] : \ + "?") #undef PWRMGR_NAME_ENTRY @@ -354,26 +421,14 @@ static void ot_pwrmgr_update_irq(OtPwrMgrState *s) ibex_irq_set(&s->irq, (int)(bool)level); } -static void ot_pwrmgr_fsm_push_event(OtPwrMgrState *s, bool trigger) -{ - s->fsm_event_count += 1u; - if (trigger) { - qemu_bh_schedule(s->fsm_tick_bh); - } -} +#define ot_pwrmgr_schedule_fsm(_s_) \ + ot_pwrmgr_xschedule_fsm(_s_, __func__, __LINE__) -static void ot_pwrmgr_fsm_pop_event(OtPwrMgrState *s) +static void ot_pwrmgr_xschedule_fsm(OtPwrMgrState *s, const char *func, + int line) { - g_assert(s->fsm_event_count); - - s->fsm_event_count -= 1u; -} - -static void ot_pwrmgr_fsm_schedule(OtPwrMgrState *s) -{ - if (s->fsm_event_count) { - qemu_bh_schedule(s->fsm_tick_bh); - } + trace_ot_pwrmgr_schedule_fsm(s->ot_id, func, line); + qemu_bh_schedule(s->fsm_tick_bh); } static void ot_pwrmgr_cdc_sync(void *opaque) @@ -389,11 +444,12 @@ static void ot_pwrmgr_rom_good(void *opaque, int n, int level) g_assert((unsigned)n < s->num_rom); - s->roms[n].good = level; + trace_ot_pwrmgr_rom(s->ot_id, n, "good", level); - trace_ot_pwrmgr_rom(s->ot_id, n, "good", s->roms[n].good); - - ot_pwrmgr_fsm_push_event(s, true); + if (level) { + s->fsm_events.rom_good |= 1u << n; + ot_pwrmgr_schedule_fsm(s); + } } static void ot_pwrmgr_rom_done(void *opaque, int n, int level) @@ -402,11 +458,12 @@ static void ot_pwrmgr_rom_done(void *opaque, int n, int level) g_assert((unsigned)n < s->num_rom); - s->roms[n].done = level; - - trace_ot_pwrmgr_rom(s->ot_id, n, "done", s->roms[n].done); + trace_ot_pwrmgr_rom(s->ot_id, n, "done", level); - ot_pwrmgr_fsm_push_event(s, true); + if (level) { + s->fsm_events.rom_done |= 1u << n; + ot_pwrmgr_schedule_fsm(s); + } } static void ot_pwrmgr_wkup(void *opaque, int irq, int level) @@ -414,11 +471,9 @@ static void ot_pwrmgr_wkup(void *opaque, int irq, int level) OtPwrMgrState *s = opaque; unsigned src = (unsigned)irq; - assert(src < OT_PWRMGR_WAKEUP_COUNT); + assert(src < PWRMGR_WAKEUP_MAX); - qemu_log_mask(LOG_UNIMP, "%s", __func__); - - trace_ot_pwrmgr_wkup(s->ot_id, WAKEUP_NAME(src), src, (bool)level); + trace_ot_pwrmgr_wkup(s->ot_id, WAKEUP_NAME(s, src), src, (bool)level); } static void ot_pwrmgr_rst_req(void *opaque, int irq, int level) @@ -426,37 +481,36 @@ static void ot_pwrmgr_rst_req(void *opaque, int irq, int level) OtPwrMgrState *s = opaque; unsigned src = (unsigned)irq; - g_assert(src < OT_PWRMGR_RST_COUNT); + g_assert(src < PWRMGR_CONFIG[s->version].reset_count); uint32_t rstmask = 1u << src; /* rst_req are stored in the LSBs */ if (level) { - trace_ot_pwrmgr_rst_req(s->ot_id, RST_NAME(src), src); + trace_ot_pwrmgr_rst_req(s->ot_id, RST_NAME(s, src), src); if (s->regs[R_RESET_STATUS]) { /* do nothing if a reset is already in progress */ /* TODO: is it true for HW vs. SW request ?*/ + trace_ot_pwrmgr_ignore_req("reset on-going"); return; } s->regs[R_RESET_STATUS] |= rstmask; - switch (irq) { - case OT_PWRMGR_RST_SYSRST: - s->reset_req.req = OT_RSTMGR_RESET_SYSCTRL; - s->reset_req.domain = OT_PWRMGR_SLOW_DOMAIN; - break; - case OT_PWRMGR_RST_AON_TIMER: - s->reset_req.req = OT_RSTMGR_RESET_AON_TIMER; - s->reset_req.domain = OT_PWRMGR_SLOW_DOMAIN; - break; - default: + g_assert(s->reset_req.domain == OT_PWRMGR_NO_DOMAIN); + + s->reset_req.domain = OT_PWRMGR_SLOW_DOMAIN; + + int req = PWRMGR_RESET_DISPATCH[s->version][src]; + if (req < 0) { + /* not yet implemented */ g_assert_not_reached(); - break; } + s->reset_req.req = req; trace_ot_pwrmgr_reset_req(s->ot_id, "scheduling reset", src); - ot_pwrmgr_fsm_push_event(s, true); + s->fsm_events.hw_reset = true; + ot_pwrmgr_schedule_fsm(s); } } @@ -481,15 +535,21 @@ static void ot_pwrmgr_sw_rst_req(void *opaque, int irq, int level) if (s->regs[R_RESET_STATUS]) { /* do nothing if a reset is already in progress */ + trace_ot_pwrmgr_ignore_req("reset on-going"); return; } + s->regs[R_RESET_STATUS] |= rstbit; + g_assert(s->reset_req.domain == OT_PWRMGR_NO_DOMAIN); + s->reset_req.req = OT_RSTMGR_RESET_SW; s->reset_req.domain = OT_PWRMGR_FAST_DOMAIN; trace_ot_pwrmgr_reset_req(s->ot_id, "scheduling SW reset", 0); - ot_pwrmgr_fsm_push_event(s, true); + + s->fsm_events.sw_reset = true; + ot_pwrmgr_schedule_fsm(s); } } @@ -512,20 +572,18 @@ static void ot_pwrmgr_fast_fsm_tick(OtPwrMgrState *s) switch (s->f_state) { case OT_PWR_FAST_ST_LOW_POWER: PWR_CHANGE_FAST_STATE(s, ENABLE_CLOCKS); - ot_pwrmgr_fsm_push_event(s, false); break; case OT_PWR_FAST_ST_ENABLE_CLOCKS: PWR_CHANGE_FAST_STATE(s, RELEASE_LC_RST); // TODO: need to release ROM controllers from reset here to emulate // they are clocked and start to verify their contents. - ot_pwrmgr_fsm_push_event(s, false); break; case OT_PWR_FAST_ST_RELEASE_LC_RST: PWR_CHANGE_FAST_STATE(s, OTP_INIT); ibex_irq_set(&s->pwr_otp_req, (int)true); break; case OT_PWR_FAST_ST_OTP_INIT: - if (s->inputs & INPUTS_OTP_MASK) { + if (s->fsm_events.otp_done) { /* release the request signal */ ibex_irq_set(&s->pwr_otp_req, (int)false); PWR_CHANGE_FAST_STATE(s, LC_INIT); @@ -533,7 +591,7 @@ static void ot_pwrmgr_fast_fsm_tick(OtPwrMgrState *s) } break; case OT_PWR_FAST_ST_LC_INIT: - if (s->inputs & INPUTS_LC_MASK) { + if (s->fsm_events.lc_done) { /* release the request signal */ ibex_irq_set(&s->pwr_lc_req, (int)false); PWR_CHANGE_FAST_STATE(s, STRAP); @@ -542,45 +600,31 @@ static void ot_pwrmgr_fast_fsm_tick(OtPwrMgrState *s) case OT_PWR_FAST_ST_STRAP: // TODO: need to sample straps PWR_CHANGE_FAST_STATE(s, ACK_PWR_UP); - ot_pwrmgr_fsm_push_event(s, false); break; case OT_PWR_FAST_ST_ACK_PWR_UP: PWR_CHANGE_FAST_STATE(s, ROM_CHECK_DONE); - ot_pwrmgr_fsm_push_event(s, false); break; case OT_PWR_FAST_ST_ROM_CHECK_DONE: - for (unsigned ix = 0; ix < s->num_rom; ix++) { - if (!s->roms[ix].done) { - break; - } + if (s->fsm_events.rom_done == (1u << s->num_rom) - 1u) { + PWR_CHANGE_FAST_STATE(s, ROM_CHECK_GOOD); } - PWR_CHANGE_FAST_STATE(s, ROM_CHECK_GOOD); break; - case OT_PWR_FAST_ST_ROM_CHECK_GOOD: { - bool success = true; - for (unsigned ix = 0; ix < s->num_rom; ix++) { - if (!s->roms[ix].good) { - success = false; - break; - } - } - if (success) { + case OT_PWR_FAST_ST_ROM_CHECK_GOOD: + if ((s->fsm_events.rom_good == (1u << s->num_rom) - 1u) && + !s->fsm_events.holdon_fetch) { PWR_CHANGE_FAST_STATE(s, ACTIVE); - ot_pwrmgr_fsm_push_event(s, false); } - } break; + break; case OT_PWR_FAST_ST_ACTIVE: if (!s->regs[R_RESET_STATUS]) { ibex_irq_set(&s->cpu_enable, (int)true); } else { ibex_irq_set(&s->cpu_enable, (int)false); PWR_CHANGE_FAST_STATE(s, DIS_CLKS); - ot_pwrmgr_fsm_push_event(s, false); } break; case OT_PWR_FAST_ST_DIS_CLKS: PWR_CHANGE_FAST_STATE(s, RESET_PREP); - ot_pwrmgr_fsm_push_event(s, false); break; case OT_PWR_FAST_ST_FALL_THROUGH: case OT_PWR_FAST_ST_NVM_IDLE_CHK: @@ -588,11 +632,12 @@ static void ot_pwrmgr_fast_fsm_tick(OtPwrMgrState *s) case OT_PWR_FAST_ST_NVM_SHUT_DOWN: qemu_log_mask(LOG_UNIMP, "%s: low power modes are not implemented\n", __func__); - break; - case OT_PWR_FAST_ST_RESET_PREP: /* fallthrough */ + /* fallthrough */ + case OT_PWR_FAST_ST_RESET_PREP: PWR_CHANGE_FAST_STATE(s, RESET_WAIT); ot_rstmgr_reset_req(s->rstmgr, (bool)s->reset_req.domain, s->reset_req.req); + s->reset_req.domain = OT_PWRMGR_NO_DOMAIN; break; /* NOLINTNEXTLINE */ case OT_PWR_FAST_ST_RESET_WAIT: @@ -608,14 +653,16 @@ static void ot_pwrmgr_fsm_tick(void *opaque) { OtPwrMgrState *s = opaque; - ot_pwrmgr_fsm_pop_event(s); - ot_pwrmgr_slow_fsm_tick(s); - ot_pwrmgr_fast_fsm_tick(s); - if (s->f_state != OT_PWR_FAST_ST_INVALID && - s->s_state != OT_PWR_SLOW_ST_INVALID) { - ot_pwrmgr_fsm_schedule(s); + OtPwrMgrFastState f_state = s->f_state; + ot_pwrmgr_fast_fsm_tick(s); + if (f_state != s->f_state) { + /* schedule FSM update once more if its state has changed */ + ot_pwrmgr_schedule_fsm(s); + } else { + /* otherwise, go idle and wait for an external event */ + trace_ot_pwrmgr_go_idle(s->ot_id, FST_NAME(s->f_state)); } } @@ -629,9 +676,9 @@ static void ot_pwrmgr_pwr_lc_rsp(void *opaque, int n, int level) g_assert(n == 0); - if (level == 1) { - s->inputs |= INPUTS_LC_MASK; - ot_pwrmgr_fsm_push_event(s, true); + if (level) { + s->fsm_events.lc_done = true; + ot_pwrmgr_schedule_fsm(s); } } @@ -641,12 +688,22 @@ static void ot_pwrmgr_pwr_otp_rsp(void *opaque, int n, int level) g_assert(n == 0); - if (level == 1) { - s->inputs |= INPUTS_OTP_MASK; - ot_pwrmgr_fsm_push_event(s, true); + if (level) { + s->fsm_events.otp_done = true; + ot_pwrmgr_schedule_fsm(s); } } +static void ot_pwrmgr_holdon_fetch(void *opaque, int n, int level) +{ + OtPwrMgrState *s = opaque; + + g_assert(n == 0); + + s->fsm_events.holdon_fetch = (bool)level; + ot_pwrmgr_schedule_fsm(s); +} + static uint64_t ot_pwrmgr_regs_read(void *opaque, hwaddr addr, unsigned size) { OtPwrMgrState *s = opaque; @@ -737,7 +794,7 @@ static void ot_pwrmgr_regs_write(void *opaque, hwaddr addr, uint64_t val64, val32 &= R_CFG_CDC_SYNC_SYNC_MASK; s->regs[reg] |= val32; /* not described as RW1S, but looks like it */ if (val32) { - timer_mod(s->cdc_sync, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + timer_mod(s->cdc_sync, qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + CDC_SYNC_PULSE_DURATION_NS); } break; @@ -788,6 +845,8 @@ static void ot_pwrmgr_regs_write(void *opaque, hwaddr addr, uint64_t val64, static Property ot_pwrmgr_properties[] = { DEFINE_PROP_STRING("ot_id", OtPwrMgrState, ot_id), DEFINE_PROP_UINT8("num-rom", OtPwrMgrState, num_rom, 0), + DEFINE_PROP_UINT8("version", OtPwrMgrState, version, UINT8_MAX), + DEFINE_PROP_BOOL("fetch-ctrl", OtPwrMgrState, fetch_ctrl, false), DEFINE_PROP_LINK("rstmgr", OtPwrMgrState, rstmgr, TYPE_OT_RSTMGR, OtRstMgrState *), DEFINE_PROP_END_OF_LIST(), @@ -801,13 +860,19 @@ static const MemoryRegionOps ot_pwrmgr_regs_ops = { .impl.max_access_size = 4u, }; -static void ot_pwrmgr_reset(DeviceState *dev) +static void ot_pwrmgr_reset_enter(Object *obj, ResetType type) { - OtPwrMgrState *s = OT_PWRMGR(dev); + OtPwrMgrClass *c = OT_PWRMGR_GET_CLASS(obj); + OtPwrMgrState *s = OT_PWRMGR(obj); g_assert(s->ot_id); + g_assert(s->version < OT_PWMGR_VERSION_COUNT); + + trace_ot_pwrmgr_reset(s->ot_id, "enter"); - trace_ot_pwrmgr_reset(s->ot_id); + if (c->parent_phases.enter) { + c->parent_phases.enter(obj, type); + } assert(s->rstmgr); @@ -818,9 +883,8 @@ static void ot_pwrmgr_reset(DeviceState *dev) s->regs[R_CONTROL] = 0x180u; s->regs[R_WAKEUP_EN_REGWEN] = 0x1u; s->regs[R_RESET_EN_REGWEN] = 0x1u; - - s->inputs = 0; - s->fsm_event_count = 0; + s->fsm_events.bitmap = 0; + s->fsm_events.holdon_fetch = s->fetch_ctrl; PWR_CHANGE_FAST_STATE(s, LOW_POWER); PWR_CHANGE_SLOW_STATE(s, RESET); @@ -830,10 +894,20 @@ static void ot_pwrmgr_reset(DeviceState *dev) ibex_irq_set(&s->pwr_otp_req, 0); ibex_irq_set(&s->pwr_lc_req, 0); ibex_irq_set(&s->alert, 0); +} - memset(s->roms, 0, s->num_rom * sizeof(OtPwrMgrRomStatus)); +static void ot_pwrmgr_reset_exit(Object *obj) +{ + OtPwrMgrClass *c = OT_PWRMGR_GET_CLASS(obj); + OtPwrMgrState *s = OT_PWRMGR(obj); - ot_pwrmgr_fsm_push_event(s, true); + trace_ot_pwrmgr_reset(s->ot_id, "exit"); + + if (c->parent_phases.exit) { + c->parent_phases.exit(obj); + } + + ot_pwrmgr_schedule_fsm(s); } static void ot_pwrmgr_realize(DeviceState *dev, Error **errp) @@ -842,14 +916,19 @@ static void ot_pwrmgr_realize(DeviceState *dev, Error **errp) (void)errp; if (s->num_rom) { - s->roms = g_new0(OtPwrMgrRomStatus, s->num_rom); - + if (s->num_rom > 8u * sizeof(uint8_t)) { + error_setg(&error_fatal, "too many ROMs\n"); + g_assert_not_reached(); + } qdev_init_gpio_in_named(dev, &ot_pwrmgr_rom_good, OT_PWRMGR_ROM_GOOD, s->num_rom); qdev_init_gpio_in_named(dev, &ot_pwrmgr_rom_done, OT_PWRMGR_ROM_DONE, s->num_rom); - } else { - s->roms = NULL; + } + + if (s->fetch_ctrl) { + qdev_init_gpio_in_named(dev, &ot_pwrmgr_holdon_fetch, + OT_PWRMGR_HOLDON_FETCH, 1u); } } @@ -868,12 +947,12 @@ static void ot_pwrmgr_init(Object *obj) ibex_qdev_init_irq(obj, &s->pwr_otp_req, OT_PWRMGR_OTP_REQ); ibex_qdev_init_irq(obj, &s->cpu_enable, OT_PWRMGR_CPU_EN); - s->cdc_sync = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_pwrmgr_cdc_sync, s); + s->cdc_sync = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_pwrmgr_cdc_sync, s); qdev_init_gpio_in_named(DEVICE(obj), &ot_pwrmgr_wkup, OT_PWRMGR_WKUP, - OT_PWRMGR_WAKEUP_COUNT); + PWRMGR_WAKEUP_MAX); qdev_init_gpio_in_named(DEVICE(obj), &ot_pwrmgr_rst_req, OT_PWRMGR_RST, - OT_PWRMGR_RST_COUNT); + PWRMGR_RESET_MAX); qdev_init_gpio_in_named(DEVICE(obj), &ot_pwrmgr_sw_rst_req, OT_PWRMGR_SW_RST, NUM_SW_RST_REQ); qdev_init_gpio_in_named(DEVICE(obj), &ot_pwrmgr_pwr_lc_rsp, @@ -890,9 +969,14 @@ static void ot_pwrmgr_class_init(ObjectClass *klass, void *data) (void)data; dc->realize = &ot_pwrmgr_realize; - dc->reset = &ot_pwrmgr_reset; device_class_set_props(dc, ot_pwrmgr_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); + + ResettableClass *rc = RESETTABLE_CLASS(dc); + OtPwrMgrClass *pc = OT_PWRMGR_CLASS(klass); + resettable_class_set_parent_phases(rc, &ot_pwrmgr_reset_enter, NULL, + &ot_pwrmgr_reset_exit, + &pc->parent_phases); } static const TypeInfo ot_pwrmgr_info = { @@ -901,6 +985,7 @@ static const TypeInfo ot_pwrmgr_info = { .instance_size = sizeof(OtPwrMgrState), .instance_init = &ot_pwrmgr_init, .class_init = &ot_pwrmgr_class_init, + .class_size = sizeof(OtPwrMgrClass) }; static void ot_pwrmgr_register_types(void) diff --git a/hw/opentitan/ot_rstmgr.c b/hw/opentitan/ot_rstmgr.c index 522a8dede23f..9abf2e0bafd0 100644 --- a/hw/opentitan/ot_rstmgr.c +++ b/hw/opentitan/ot_rstmgr.c @@ -47,6 +47,7 @@ #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" #include "hw/sysbus.h" +#include "sysemu/hw_accel.h" #include "trace.h" @@ -151,6 +152,8 @@ struct OtRstMgrState { MemoryRegion mmio; IbexIRQ sw_reset; IbexIRQ alert; + QEMUBH *bus_reset_bh; + CPUState *cpu; uint32_t *regs; @@ -208,17 +211,36 @@ void ot_rstmgr_reset_req(OtRstMgrState *s, bool fastclk, OtRstMgrResetReq req) trace_ot_rstmgr_reset_req(REQ_NAME(req), req, fastclk); - /* - * Reset all devices connected to RSTMGR parent bus, i.e. OpenTitan devices - * TODO: manage reset tree (depending on power domains, etc.) - */ - bus_cold_reset(s->parent_obj.parent_obj.parent_bus); + qemu_bh_schedule(s->bus_reset_bh); } /* -------------------------------------------------------------------------- */ /* Private implementation */ /* -------------------------------------------------------------------------- */ +static void ot_rstmgr_reset_bus(void *opaque) +{ + OtRstMgrState *s = opaque; + + /* request the vCPU to stop */ + s->cpu->stop = true; + + /* wait for the vCPU to stop */ + while (!s->cpu->stopped) { + qemu_mutex_unlock_iothread(); + qemu_cpu_kick(s->cpu); + qemu_mutex_lock_iothread(); + } + qemu_notify_event(); + + cpu_synchronize_state(s->cpu); + /* Reset all OpenTitan devices connected to RSTMGR parent bus */ + bus_cold_reset(s->parent_obj.parent_obj.parent_bus); + cpu_synchronize_post_reset(s->cpu); + + /* TODO: manage reset tree (depending on power domains, etc.) */ +} + static int ot_rstmgr_sw_rst_walker(DeviceState *dev, void *opaque) { OtRstMgrResetDesc *desc = opaque; @@ -249,8 +271,8 @@ static void ot_rstmgr_update_sw_reset(OtRstMgrState *s, unsigned devix) const OtRstMgrResettable *rst = &SW_RESETTABLE_DEVICES[devix]; if (!rst->typename) { - qemu_log_mask(LOG_UNIMP, "Reset for slot %u not yet implemented", - devix); + qemu_log_mask(LOG_UNIMP, "%s: Reset for slot %u not yet implemented", + __func__, devix); return; } @@ -259,13 +281,15 @@ static void ot_rstmgr_update_sw_reset(OtRstMgrState *s, unsigned devix) desc.path = g_strdup_printf("%s[%d]", rst->typename, rst->idx); desc.reset = !s->regs[R_SW_RST_CTRL_N_0 + devix]; + trace_ot_rstmgr_sw_reset(desc.path); + /* search for the device on the same local bus */ int res = qbus_walk_children(s->parent_obj.parent_obj.parent_bus, &ot_rstmgr_sw_rst_walker, NULL, NULL, NULL, &desc); if (res >= 0) { - qemu_log_mask(LOG_GUEST_ERROR, "rstmgr: unable to locate device %s", - desc.path); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Unable to locate device %s", + __func__, desc.path); } g_free(desc.path); @@ -459,6 +483,15 @@ static void ot_rstmgr_reset(DeviceState *dev) trace_ot_rstmgr_reset(); + if (!s->cpu) { + CPUState *cpu = ot_common_get_local_cpu(DEVICE(s)); + if (!cpu) { + error_setg(&error_fatal, "Could not find the associated vCPU"); + g_assert_not_reached(); + } + s->cpu = cpu; + } + s->regs[R_RESET_REQ] = OT_MULTIBITBOOL4_FALSE; if (s->por) { memset(s->regs, 0, REGS_SIZE); @@ -494,6 +527,8 @@ static void ot_rstmgr_init(Object *obj) ibex_qdev_init_irq(obj, &s->sw_reset, OT_RSTMGR_SW_RST); ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + + s->bus_reset_bh = qemu_bh_new(&ot_rstmgr_reset_bus, s); } static void ot_rstmgr_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_spi_device.c b/hw/opentitan/ot_spi_device.c index 1a9e46cd7be3..0139d841c2a6 100644 --- a/hw/opentitan/ot_spi_device.c +++ b/hw/opentitan/ot_spi_device.c @@ -1100,7 +1100,7 @@ static void ot_spi_device_flash_pace_spibus(OtSPIDeviceState *s) SpiDeviceFlash *f = &s->flash; timer_del(f->irq_timer); - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); trace_ot_spi_device_flash_pace("set", timer_pending(f->irq_timer)); timer_mod(f->irq_timer, (int64_t)(now + SPI_BUS_FLASH_READ_DELAY_NS)); } @@ -2359,7 +2359,7 @@ static void ot_spi_device_chr_recv_generic(OtSPIDeviceState *s, count--; } if (!fifo8_is_empty(&g->rx_fifo) && bus->byte_count) { - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); /* todo: use R_CFG_TIMER_V field to change the timeout */ timer_mod(g->rx_timer, (int64_t)(now + SPI_BUS_TIMEOUT_NS)); } @@ -2673,9 +2673,9 @@ static void ot_spi_device_init(Object *obj) * co-operative multitasking between the vCPU and the IO thread */ f->irq_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_spi_device_flash_resume_read, s); - g->rx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, - &ot_spi_device_recv_generic_timeout, s); + timer_new_ns(OT_VIRTUAL_CLOCK, &ot_spi_device_flash_resume_read, s); + g->rx_timer = + timer_new_ns(OT_VIRTUAL_CLOCK, &ot_spi_device_recv_generic_timeout, s); } static void ot_spi_device_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_spi_host.c b/hw/opentitan/ot_spi_host.c index 77ba33d76749..426484bff6a7 100644 --- a/hw/opentitan/ot_spi_host.c +++ b/hw/opentitan/ot_spi_host.c @@ -45,6 +45,7 @@ #include "hw/hw.h" #include "hw/irq.h" #include "hw/opentitan/ot_alert.h" +#include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_spi_host.h" #include "hw/qdev-properties-system.h" #include "hw/qdev-properties.h" @@ -840,7 +841,7 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause) headcmd->ongoing = ongoing; timer_mod(s->fsm_delay, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + FSM_TRIGGER_DELAY_NS); + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + FSM_TRIGGER_DELAY_NS); ot_spi_host_trace_status("S<", ot_spi_host_get_status(s)); } @@ -1277,7 +1278,7 @@ static void ot_spi_host_instance_init(Object *obj) cmdfifo_create(s->cmd_fifo, CMDFIFO_LEN); s->fsm_bh = qemu_bh_new(&ot_spi_host_schedule_fsm, s); - s->fsm_delay = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ot_spi_host_post_fsm, s); + s->fsm_delay = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_spi_host_post_fsm, s); } static void ot_spi_host_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_timer.c b/hw/opentitan/ot_timer.c index 1dd9489c2376..ae6a98cc4f20 100644 --- a/hw/opentitan/ot_timer.c +++ b/hw/opentitan/ot_timer.c @@ -29,6 +29,7 @@ #include "qemu/log.h" #include "qemu/timer.h" #include "hw/opentitan/ot_alert.h" +#include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_timer.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" @@ -160,7 +161,7 @@ static void ot_timer_update_irqs(OtTimerState *s) static void ot_timer_rearm(OtTimerState *s, bool reset_origin) { - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); if (reset_origin) { s->origin_ns = now; @@ -211,14 +212,14 @@ static uint64_t ot_timer_read(void *opaque, hwaddr addr, unsigned size) break; case R_TIMER_V_LOWER0: { int64_t now = ot_timer_is_active(s) ? - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) : + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) : s->origin_ns; val32 = ot_timer_get_mtime(s, now); break; } case R_TIMER_V_UPPER0: { int64_t now = ot_timer_is_active(s) ? - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) : + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) : s->origin_ns; val32 = ot_timer_get_mtime(s, now) >> 32u; break; @@ -272,7 +273,7 @@ static void ot_timer_write(void *opaque, hwaddr addr, uint64_t value, /* stop timer */ timer_del(s->timer); /* save current mtime */ - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); uint64_t mtime = ot_timer_get_mtime(s, now); s->regs[R_TIMER_V_LOWER0] = (uint32_t)mtime; s->regs[R_TIMER_V_UPPER0] = (uint32_t)(mtime >> 32u); @@ -292,7 +293,7 @@ static void ot_timer_write(void *opaque, hwaddr addr, uint64_t value, * schedule the timer for the next peripheral clock tick to check again * for interrupt condition */ - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); int64_t next = ot_timer_compute_next_timeout(s, now, 0); timer_mod_anticipate(s->timer, next); break; @@ -373,7 +374,7 @@ static void ot_timer_init(Object *obj) REGS_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); - s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, &ot_timer_cb, s); + s->timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_timer_cb, s); } static void ot_timer_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index ad32243f1060..c2b4386fe633 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -44,8 +44,10 @@ ot_csrng_change_state(int line, const char *old, int nold, const char *new, int ot_csrng_command_scheduler(unsigned slot, const char *action) "#%u: %s" ot_csrng_complete_command(unsigned slot, const char *kind, const char *cmd, unsigned acmd, int res) "#%u (%s) acmd: %s(%u): %d" ot_csrng_connection(unsigned slot) "#%u" +ot_csrng_defer_generation(unsigned slot) "#%u instanciation not yet completed" ot_csrng_end_of_gen(unsigned slot, unsigned rempack) "#%u rem %u" ot_csrng_entropy_injecter(unsigned slot, const char *action) "#%u: %s" +ot_csrng_entropy_rejected(unsigned slot, const char *reason, int res) "#%u: %s (%d)" ot_csrng_error(const char *func, int line, const char *err) "%s:%d %s" ot_csrng_expedite_uninstantiation(unsigned slot) "#%u" ot_csrng_fill_entropy(unsigned slot, bool fips) "#%u fips %u" @@ -53,15 +55,18 @@ ot_csrng_generate(unsigned slot, unsigned count) "#%u %u packets to generate" ot_csrng_hwapp_need_entropy(unsigned slot, const char *msg) "#%u: %s" ot_csrng_hwapp_ready(unsigned slot, bool ready, unsigned rem) "#%u: %u rem %u" ot_csrng_info(const char *func, int line, const char *msg, uint32_t value) "%s:%d %s: 0x%08x" -ot_csrng_instanciate(unsigned slot, bool on) "#%u: %u" +ot_csrng_instantiate(unsigned slot, bool on) "#%u: %u" ot_csrng_invalid_state(const char *func, const char *state, int st) "%s [%s:%d]" ot_csrng_io_read_out(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_csrng_io_write(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_csrng_irqs(uint32_t active, uint32_t mask, uint32_t eff) "act:0x%08x msk:0x%08x eff:0x%08x" ot_csrng_push_command(unsigned slot, const char *cmd, unsigned acmd, char code, unsigned len) "#%u: %s(%u) %clen: %u" ot_csrng_read_state_db(unsigned slot, unsigned pos, uint32_t val) "#%u [%u] = 0x%08x" +ot_csrng_request_entropy(unsigned slot, int gen) "#%u gen %d" ot_csrng_retry_es_init(unsigned retry_count) "rescheduling initial ES request: %u to go" +ot_csrng_reset(void) "" ot_csrng_schedule(unsigned slot, const char *kind) "#%u: %s" +ot_csrng_scheduling_command(unsigned slot) "#%u" ot_csrng_show_buffer(const char *func, int line, unsigned appid, const char *msg, const char *hexstr) "%s:%u #%u %s: %s" ot_csrng_show_command(const char *msg, unsigned slot, const char *cmd, unsigned acmd) "%s slot #%u, acmd: %s(%u)" ot_csrng_swapp_fill(unsigned count) "%u to go" @@ -83,7 +88,7 @@ ot_dev_proxy_write_reg(const char *prefix, unsigned devix, unsigned offset, unsi ot_dm_tl_invalid_addr(uint32_t addr) "0x%x" ot_dm_tl_update(uint32_t addr, uint32_t value, const char *msg, uint32_t res) "0x%x: 0x%x (%s): %u" -ot_dm_tl_capture(uint32_t addr, uint32_t value) "0x%x: %u" +ot_dm_tl_capture(uint32_t addr, uint32_t value) "0x%x: 0x%08x" # ot_dma.c @@ -103,24 +108,25 @@ ot_dma_transfer(const char *did, const char *dir, const char *asname, uint64_t a ot_edn_change_state(unsigned appid, int line, const char *old, int nold, const char *new, int nnew) "a#%u @ %d [%s:%d] -> [%s:%d]" ot_edn_connect_endpoint(unsigned appid, unsigned epid) "a#%u:e#%u" -ot_edn_ctrl_in_state(unsigned appid, const char *state, int nstate) "a#%u [%s:%d]" ot_edn_csrng_ack(unsigned appid, const char *state, int level) "a#%u %s %d" +ot_edn_ctrl_in_state(unsigned appid, const char *state, int nstate) "a#%u [%s:%d]" +ot_edn_dinfo(unsigned appid, const char *func, int line, const char *msg, uint32_t value) "a#%u %s:%d %s %u" ot_edn_enable(unsigned appid, const char *msg) "a#%u: %s" ot_edn_ep_fifo(unsigned appid, const char *msg, unsigned remwslot) "a#%u %s rem:%u" ot_edn_ep_request(unsigned appid, bool avail, const char *state, int st, bool refill, unsigned rem) "a#%u avail %u, [%s:%d], refill %u, rem %u" ot_edn_error(unsigned appid, const char *func, int line, const char *err) "a#%u %s:%d %s" ot_edn_fill_bits(unsigned appid, unsigned rem, bool packet_fips, bool fips) "a#%u rem %u, fips %u/%u" ot_edn_fill_endpoint(unsigned appid, unsigned epid, uint32_t bits, bool fips, size_t gcnt, size_t tcnt) "a#%u:e#%u bits 0x%08x fips %u count %lu/%lu" -ot_edn_dinfo(unsigned appid, const char *func, int line, const char *msg, uint32_t value) "a#%u %s:%d %s %u" -ot_edn_xinfo(unsigned appid, const char *func, int line, const char *msg, uint32_t value) "a#%u %s:%d %s 0x%08x" +ot_edn_handle_ep_request(unsigned appid, unsigned epid) "a#%u:e#%u" ot_edn_invalid_state(unsigned appid, const char *func, const char *state, int st) "a#%u %s [%s:%d]" ot_edn_io_read_out(unsigned appid, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "a#%u addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_edn_io_write(unsigned appid, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "a#%u addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_edn_irqs(unsigned appid, uint32_t active, uint32_t mask, uint32_t eff) "#%u act:0x%08x msk:0x%08x eff:0x%08x" ot_edn_request_entropy(unsigned appid, unsigned epid) "a#%u:e#%u" +ot_edn_reset(unsigned appid) "a#%u" ot_edn_schedule(unsigned appid, const char *cause) "a#%u %s" -ot_edn_handle_ep_request(unsigned appid, unsigned epid) "a#%u:e#%u" ot_edn_update_genbits_ready(unsigned appid, unsigned rem, unsigned fslot, bool accept) "a#%u rem packet %u, free slot %u, accept? %u" +ot_edn_xinfo(unsigned appid, const char *func, int line, const char *msg, uint32_t value) "a#%u %s:%d %s 0x%08x" # ot_entropy_src.c @@ -130,7 +136,7 @@ ot_entropy_src_consume_entropy(bool obs_fifo, bool bypass, bool hw_path, unsigne ot_entropy_src_error(const char *msg, const char *state, int st) "%s [%s:%u]" ot_entropy_src_fill_noise(unsigned count, unsigned infifo) "up to %u, input fifo %u" ot_entropy_src_info(const char *msg) "%s" -ot_entropy_src_init_ongoing(const char *state, int st) "entropy source still initializing in [%s:%u]" +ot_entropy_src_init_ongoing(const char *state, int st, int ns) "ES still initializing in [%s:%u] %d ns to go" ot_entropy_src_io_read_out(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_entropy_src_io_write(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_entropy_src_is_fips_capable(bool en, bool es_route, bool es_type, bool rng_bit_en, bool res) "en:%u rt:%u tp:%u !rb:%u => %u" @@ -138,6 +144,7 @@ ot_entropy_src_no_entropy(unsigned count) "only %u words available" ot_entropy_src_obs_fifo(unsigned level, unsigned thold) "level %u, threshold %u" ot_entropy_src_otp_conf(bool fw_read, bool fw_over) "fw_read %u, fw_over %u" ot_entropy_src_push_bypass_entropy(unsigned slot) "final FIFO depth: %u" +ot_entropy_src_reset(void) "" ot_entropy_src_show_buffer(const char *func, int line, const char *msg, const char *hexstr) "%s:%u %s: %s" ot_entropy_src_update_filler(bool iok, bool ook, bool pok, bool all) "in %u, out %u, proc %u -> %u" ot_entropy_src_update_generation(unsigned gennum) "%u" @@ -152,6 +159,7 @@ ot_flash_op_complete(int op, bool success) "%d: %u" ot_flash_error(const char *func, int line, const char *err) "%s:%d %s" ot_flash_info(const char *func, int line, const char *msg, uint32_t value) "%s:%d %s: 0x%08x" ot_flash_info_part(uint32_t op_addr, unsigned bank, unsigned infosel, uint32_t addr) "op_addr 0x%06x bank %u infosel %u addr 0x%06x" +ot_flash_irqs(uint32_t active, uint32_t mask, uint32_t eff) "act:0x%08x msk:0x%08x eff:0x%08x" # ot_gpio.c @@ -271,12 +279,15 @@ ot_pinmux_io_write(uint32_t addr, uint32_t val, uint32_t pc) "addr=0x%02x, val=0 # ot_pwrmgr.c ot_pwrmgr_change_state(const char *id, int line, const char *type, const char *old, int nold, const char *new, int nnew) "%s @ %d %s: [%s:%d] -> [%s:%d]" +ot_pwrmgr_go_idle(const char *id, const char *state) "%s: %s" +ot_pwrmgr_ignore_req(const char *reason) "%s" ot_pwrmgr_io_read_out(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_pwrmgr_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" -ot_pwrmgr_reset(const char *id) "%s" +ot_pwrmgr_reset(const char *id, const char *action) "%s: %s" ot_pwrmgr_reset_req(const char *id, const char *name, unsigned val) "%s: %s: %u" ot_pwrmgr_rom(const char *id, int n, const char *what, bool val) "%s rom #%u %s=%u" ot_pwrmgr_rst_req(const char *id, const char *name, unsigned src) "%s %s(%u)" +ot_pwrmgr_schedule_fsm(const char *id, const char *func, int line) "%s @ %s:%d" ot_pwrmgr_sw_rst_req(const char *id, unsigned src, bool active) "%s: %u: %u" ot_pwrmgr_wkup(const char *id, const char *name, unsigned src, bool active) "%s: %s(%u): %u" @@ -295,6 +306,7 @@ ot_rstmgr_io_read_out(uint32_t addr, const char * regname, uint32_t val, uint32_ ot_rstmgr_io_write(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_rstmgr_reset(void) "" ot_rstmgr_reset_req(const char *req, unsigned reqix, bool fastclk) "%s(%u) @%u" +ot_rstmgr_sw_reset(const char *devpath) "SW reset %s" ot_rstmgr_sw_rst(const char *path, bool reset) "%s: reset:%u" # ot_sensor.c diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index c3f11dd08c8a..a57387423495 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -44,7 +44,7 @@ config OT_DARJEELING select OT_SRAM_CTRL select OT_TIMER select OT_UART - select RISCV_DMI + select RISCV_DTM select SIFIVE_PLIC select SPLIT_IRQ @@ -138,7 +138,7 @@ config RISCV_VIRT config RISCV_DEBUG bool -config RISCV_DMI +config RISCV_DTM bool config SHAKTI_C diff --git a/hw/riscv/dmi.c b/hw/riscv/dtm.c similarity index 73% rename from hw/riscv/dmi.c rename to hw/riscv/dtm.c index 8f7c6a557182..7792f6a72fd0 100644 --- a/hw/riscv/dmi.c +++ b/hw/riscv/dtm.c @@ -1,5 +1,5 @@ /* - * QEMU Debug Module Interface and Controller + * QEMU Debug Transport Module * * Copyright (c) 2022-2024 Rivos, Inc. * Author(s): @@ -25,7 +25,7 @@ * * Generated code for absract commands has been extracted from the PULP Debug * module whose file (dm_mem.sv) contains the following copyright. This piece of - * code is self contained within the `riscv_dmi_dm_access_register` function: + * code is self contained within the `riscv_dtm_dm_access_register` function: * * Copyright and related rights are licensed under the Solderpad Hardware * License, Version 0.51 (the “License”); you may not use this file except in @@ -57,7 +57,7 @@ #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/debug.h" -#include "hw/riscv/dmi.h" +#include "hw/riscv/dtm.h" #include "hw/sysbus.h" #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" @@ -86,18 +86,21 @@ REG64(DMI, 0x11u) FIELD(DMI, DATA, 2u, 32u) FIELD(DMI, ADDRESS, 34u, 64u-34u) /* real width is a runtime property */ -/* - * Macros - */ - -#define xtrace_riscv_dmi_error(_msg_) \ - trace_riscv_dmi_error(__func__, __LINE__, _msg_) -#define xtrace_riscv_dmi_info(_msg_, _val_) \ - trace_riscv_dmi_info(__func__, __LINE__, _msg_, _val_) +#define xtrace_riscv_dtm_error(_msg_) \ + trace_riscv_dtm_error(__func__, __LINE__, _msg_) +#define xtrace_riscv_dtm_info(_msg_, _val_) \ + trace_riscv_dtm_info(__func__, __LINE__, _msg_, _val_) /* - * Type definitions + * DMI register operations + * see RISC-V debug spec secttion 6.1.5 Debug Module Interface Access */ +typedef enum { + DMI_IGNORE, + DMI_READ, + DMI_WRITE, + DMI_RESERVED, +} RISCVDMIOperation; typedef QLIST_HEAD(, RISCVDebugModule) RISCVDebugModuleList; @@ -110,7 +113,7 @@ typedef struct RISCVDebugModule { } RISCVDebugModule; /** Debug Module Interface */ -struct RISCVDMIState { +struct RISCVDTMState { DeviceState parent; RISCVDebugModuleList dms; @@ -129,37 +132,37 @@ struct RISCVDMIState { * Forward declarations */ -static void riscv_dmi_reset(DeviceState *dev); -static RISCVDebugModule* riscv_dmi_get_dm(RISCVDMIState *s, uint32_t addr); -static void riscv_dmi_sort_dms(RISCVDMIState *s); +static void riscv_dtm_reset(DeviceState *dev); +static RISCVDebugModule* riscv_dtm_get_dm(RISCVDTMState *s, uint32_t addr); +static void riscv_dtm_sort_dms(RISCVDTMState *s); -static void riscv_dmi_tap_dtmcs_capture(TAPDataHandler *tdh); -static void riscv_dmi_tap_dtmcs_update(TAPDataHandler *tdh); -static void riscv_dmi_tap_dmi_capture(TAPDataHandler *tdh); -static void riscv_dmi_tap_dmi_update(TAPDataHandler *tdh); +static void riscv_dtm_tap_dtmcs_capture(TAPDataHandler *tdh); +static void riscv_dtm_tap_dtmcs_update(TAPDataHandler *tdh); +static void riscv_dtm_tap_dmi_capture(TAPDataHandler *tdh); +static void riscv_dtm_tap_dmi_update(TAPDataHandler *tdh); /* * Constants */ -#define RISCV_DEBUG_DMI_VERSION 1u /* RISC-V Debug spec 0.13.x & 1.0 */ -#define RISCVDMI_DTMCS_IR 0x10u -#define RISCVDMI_DMI_IR 0x11u +#define RISCV_DEBUG_DMI_VERSION 1u /* RISC-V Debug spec 0.13.x & 1.0 */ +#define RISCVDMI_DTMCS_IR 0x10u +#define RISCVDMI_DMI_IR 0x11u static const TAPDataHandler RISCVDMI_DTMCS = { .name = "dtmcs", .length = 32u, .value = RISCV_DEBUG_DMI_VERSION, /* abits updated at runtime */ - .capture = &riscv_dmi_tap_dtmcs_capture, - .update = &riscv_dmi_tap_dtmcs_update, + .capture = &riscv_dtm_tap_dtmcs_capture, + .update = &riscv_dtm_tap_dtmcs_update, }; static const TAPDataHandler RISCVDMI_DMI = { .name = "dmi", /* data, op; abits updated at runtime */ .length = R_DMI_OP_LENGTH + R_DMI_DATA_LENGTH, - .capture = &riscv_dmi_tap_dmi_capture, - .update = &riscv_dmi_tap_dmi_update, + .capture = &riscv_dtm_tap_dmi_capture, + .update = &riscv_dtm_tap_dmi_update, }; #define MAKE_RUNSTATE_ENTRY(_ent_) [RUN_STATE_##_ent_] = stringify(_ent_) @@ -194,10 +197,10 @@ static const char *RISCVDMI_RUNSTATE_NAMES[] = { /* Public API */ /* -------------------------------------------------------------------------- */ -bool riscv_dmi_register_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, +bool riscv_dtm_register_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, hwaddr base_addr, hwaddr size) { - RISCVDMIState *s = RISCV_DMI(dev); + RISCVDTMState *s = RISCV_DTM(dev); if ((base_addr + size - 1u) > (1u << s->abits)) { error_setg(&error_fatal, @@ -235,10 +238,10 @@ bool riscv_dmi_register_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, QLIST_INSERT_HEAD(&s->dms, dm, entry); s->last_dm = dm; - trace_riscv_dmi_register_dm(count, base_addr, base_addr + size - 1u, + trace_riscv_dtm_register_dm(count, base_addr, base_addr + size - 1u, s->jtag_ok); - riscv_dmi_sort_dms(s); + riscv_dtm_sort_dms(s); return s->jtag_ok; } @@ -247,19 +250,20 @@ bool riscv_dmi_register_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, /* DTMCS/DMI implementation */ /* -------------------------------------------------------------------------- */ -static void riscv_dmi_tap_dtmcs_capture(TAPDataHandler *tdh) +static void riscv_dtm_tap_dtmcs_capture(TAPDataHandler *tdh) { - RISCVDMIState *s = tdh->opaque; + RISCVDTMState *s = tdh->opaque; tdh->value = (s->abits << 4u) | (RISCV_DEBUG_DMI_VERSION << 0u) | ((uint64_t)s->dmistat << 10u); /* see DMI op result */ } -static void riscv_dmi_tap_dtmcs_update(TAPDataHandler *tdh) +static void riscv_dtm_tap_dtmcs_update(TAPDataHandler *tdh) { - RISCVDMIState *s = tdh->opaque; + RISCVDTMState *s = tdh->opaque; if (tdh->value & (1u << 16u)) { /* dmireset */ + trace_riscv_dtm_dtmcs_reset(); s->dmistat = RISCV_DEBUG_NOERR; } if (tdh->value & (1u << 17u)) { @@ -268,25 +272,26 @@ static void riscv_dmi_tap_dtmcs_update(TAPDataHandler *tdh) } } -static void riscv_dmi_tap_dmi_capture(TAPDataHandler *tdh) +static void riscv_dtm_tap_dmi_capture(TAPDataHandler *tdh) { - RISCVDMIState *s = tdh->opaque; + RISCVDTMState *s = tdh->opaque; uint32_t addr = s->address; - uint32_t value; + uint32_t value = 0; if (s->dmistat == RISCV_DEBUG_NOERR) { - RISCVDebugModule *dm = riscv_dmi_get_dm(s, addr); - if (!dm) { - s->dmistat = RISCV_DEBUG_FAILED; - value = 0; - qemu_log_mask(LOG_UNIMP, "%s: Unknown DM address 0x%x\n", __func__, - addr); - } else { - value = dm->dc->read_value(dm->dev); + unsigned op = (unsigned)(tdh->value & 0b11); + if (op == DMI_READ) { + RISCVDebugModule *dm = riscv_dtm_get_dm(s, addr); + if (!dm) { + s->dmistat = RISCV_DEBUG_FAILED; + value = 0; + qemu_log_mask(LOG_UNIMP, "%s: Unknown DM address 0x%x\n", __func__, + addr); + } else { + value = dm->dc->read_value(dm->dev); + } } - } else { - value = 0; } /* @@ -297,23 +302,32 @@ static void riscv_dmi_tap_dmi_capture(TAPDataHandler *tdh) ((uint64_t)(s->dmistat & 0b11)); } -static void riscv_dmi_tap_dmi_update(TAPDataHandler *tdh) +static void riscv_dtm_tap_dmi_update(TAPDataHandler *tdh) { - RISCVDMIState *s = tdh->opaque; + RISCVDTMState *s = tdh->opaque; uint32_t value; uint32_t addr = (uint32_t)extract64(tdh->value, R_DMI_ADDRESS_SHIFT, (int)s->abits); unsigned op = (unsigned)(tdh->value & 0b11); + if (op == DMI_IGNORE) { + /* + * Don’t send anything over the DMI during Update-DR. This operation + * should never result in a busy or error response. The address and data + * reported in the following Capture-DR are undefined. + */ + return; + } + /* store address for next read back */ s->address = addr; - RISCVDebugModule *dm = riscv_dmi_get_dm(s, addr); + RISCVDebugModule *dm = riscv_dtm_get_dm(s, addr); if (!dm) { s->dmistat = RISCV_DEBUG_FAILED; - qemu_log_mask(LOG_UNIMP, "%s: Unknown DM address 0x%x\n", __func__, - addr); + qemu_log_mask(LOG_UNIMP, "%s: Unknown DM address 0x%x, op %u\n", + __func__, addr, op); return; } @@ -322,28 +336,24 @@ static void riscv_dmi_tap_dmi_update(TAPDataHandler *tdh) * current status reported in op is sticky. */ switch (op) { - case 0: /* NOP */ - /* - * Don’t send anything over the DMI during Update-DR. This operation - * should never result in a busy or error response. The address and data - * reported in the following Capture-DR are undefined. - */ + case DMI_IGNORE: /* NOP */ + g_assert_not_reached(); return; - case 1: /* READ from address */ + case DMI_READ: s->dmistat = dm->dc->read_rq(dm->dev, addr - dm->base); break; - case 2: /* WRITE to address */ + case DMI_WRITE: value = (uint32_t)FIELD_EX64(tdh->value, DMI, DATA); s->dmistat = dm->dc->write_rq(dm->dev, addr - dm->base, value); break; - case 3: + case DMI_RESERVED: default: s->dmistat = RISCV_DEBUG_FAILED; qemu_log_mask(LOG_UNIMP, "%s: Unknown operation %u\n", __func__, op); } } -static void riscv_dmi_register_tap_handlers(RISCVDMIState *s) +static void riscv_dtm_register_tap_handlers(RISCVDTMState *s) { /* * copy the template to update the opaque value @@ -355,7 +365,7 @@ static void riscv_dmi_register_tap_handlers(RISCVDMIState *s) tdh.value |= s->abits << 4u; /* add address bit count */ tdh.opaque = s; if (jtag_register_handler(RISCVDMI_DTMCS_IR, &tdh)) { - xtrace_riscv_dmi_error("cannot register DMTCS"); + xtrace_riscv_dtm_error("cannot register DMTCS"); return; } @@ -364,12 +374,12 @@ static void riscv_dmi_register_tap_handlers(RISCVDMIState *s) tdh.opaque = s; /* the data handler is copied by the TAP controller */ if (jtag_register_handler(RISCVDMI_DMI_IR, &tdh)) { - xtrace_riscv_dmi_error("cannot register DMI"); + xtrace_riscv_dtm_error("cannot register DMI"); return; } } -static RISCVDebugModule *riscv_dmi_get_dm(RISCVDMIState *s, uint32_t addr) +static RISCVDebugModule *riscv_dtm_get_dm(RISCVDTMState *s, uint32_t addr) { RISCVDebugModule *dm = s->last_dm; @@ -388,21 +398,21 @@ static RISCVDebugModule *riscv_dmi_get_dm(RISCVDMIState *s, uint32_t addr) return NULL; } -static void riscv_dmi_vm_state_change(void *opaque, bool running, +static void riscv_dtm_vm_state_change(void *opaque, bool running, RunState state) { (void)opaque; (void)running; - trace_riscv_dmi_vm_state_change(RUNSTATE_NAME(state), state); + trace_riscv_dtm_vm_state_change(RUNSTATE_NAME(state), state); } -static int riscv_dmi_order_dm(const void *pdm1, const void *pdm2) +static int riscv_dtm_order_dm(const void *pdm1, const void *pdm2) { return ((int)(*(RISCVDebugModule **)pdm1)->base) - ((int)(*(RISCVDebugModule **)pdm2)->base); } -static void riscv_dmi_sort_dms(RISCVDMIState *s) +static void riscv_dtm_sort_dms(RISCVDTMState *s) { RISCVDebugModule *dm; @@ -420,7 +430,7 @@ static void riscv_dmi_sort_dms(RISCVDMIState *s) } /* sort DM reference by increasing base address */ - qsort(dma, count, sizeof(RISCVDebugModule *), &riscv_dmi_order_dm); + qsort(dma, count, sizeof(RISCVDebugModule *), &riscv_dtm_order_dm); /* create a new list of ordered, managed DMs */ RISCVDebugModuleList sorted; @@ -441,27 +451,22 @@ static void riscv_dmi_sort_dms(RISCVDMIState *s) g_free(dma); } -static Property riscv_dmi_properties[] = { - DEFINE_PROP_UINT32("abits", RISCVDMIState, abits, 0x7u), +static Property riscv_dtm_properties[] = { + DEFINE_PROP_UINT32("abits", RISCVDTMState, abits, 0x7u), DEFINE_PROP_END_OF_LIST(), }; -static void riscv_dmi_reset(DeviceState *dev) +static void riscv_dtm_reset(DeviceState *dev) { - RISCVDMIState *s = RISCV_DMI(dev); + RISCVDTMState *s = RISCV_DTM(dev); s->address = 0; s->last_dm = NULL; - - if (!s->jtag_ok) { - /* JTAG not enabled, nothing more can be done for this session */ - return; - } } -static void riscv_dmi_realize(DeviceState *dev, Error **errp) +static void riscv_dtm_realize(DeviceState *dev, Error **errp) { - RISCVDMIState *s = RISCV_DMI(dev); + RISCVDTMState *s = RISCV_DTM(dev); if (s->abits < 7u || s->abits > 30u) { error_setg(errp, "Invalid address bit count"); @@ -472,41 +477,41 @@ static void riscv_dmi_realize(DeviceState *dev, Error **errp) s->jtag_ok = jtag_tap_enabled(); if (s->jtag_ok) { - (void)riscv_dmi_register_tap_handlers(s); + (void)riscv_dtm_register_tap_handlers(s); } } -static void riscv_dmi_init(Object *obj) +static void riscv_dtm_init(Object *obj) { - RISCVDMIState *s = RISCV_DMI(obj); + RISCVDTMState *s = RISCV_DTM(obj); - qemu_add_vm_change_state_handler(&riscv_dmi_vm_state_change, s); + qemu_add_vm_change_state_handler(&riscv_dtm_vm_state_change, s); QLIST_INIT(&s->dms); } -static void riscv_dmi_class_init(ObjectClass *klass, void *data) +static void riscv_dtm_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); (void)data; - dc->reset = &riscv_dmi_reset; - dc->realize = &riscv_dmi_realize; - device_class_set_props(dc, riscv_dmi_properties); + dc->reset = &riscv_dtm_reset; + dc->realize = &riscv_dtm_realize; + device_class_set_props(dc, riscv_dtm_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); } -static const TypeInfo riscv_dmi_info = { - .name = TYPE_RISCV_DMI, +static const TypeInfo riscv_dtm_info = { + .name = TYPE_RISCV_DTM, .parent = TYPE_DEVICE, - .instance_size = sizeof(RISCVDMIState), - .instance_init = &riscv_dmi_init, - .class_init = &riscv_dmi_class_init, + .instance_size = sizeof(RISCVDTMState), + .instance_init = &riscv_dtm_init, + .class_init = &riscv_dtm_class_init, }; -static void riscv_dmi_register_types(void) +static void riscv_dtm_register_types(void) { - type_register_static(&riscv_dmi_info); + type_register_static(&riscv_dtm_info); } -type_init(riscv_dmi_register_types); +type_init(riscv_dtm_register_types); diff --git a/hw/riscv/ibex_common.c b/hw/riscv/ibex_common.c index 36eb942a2c02..5a013dcf8dbe 100644 --- a/hw/riscv/ibex_common.c +++ b/hw/riscv/ibex_common.c @@ -38,6 +38,7 @@ #include "hw/riscv/ibex_common.h" #include "hw/sysbus.h" #include "monitor/monitor.h" +#include "sysemu/runstate.h" static void rust_demangle_fn(const char *st_name, int st_info, uint64_t st_value, uint64_t st_size); @@ -615,7 +616,8 @@ uint32_t ibex_load_kernel(AddressSpace *as) &kernel_entry, NULL, NULL, NULL, 0, EM_RISCV, 1, 0, as, true, &rust_demangle_fn) <= 0) { error_report("Cannot load ELF kernel %s", ms->kernel_filename); - exit(EXIT_FAILURE); + qemu_system_shutdown_request_with_code(SHUTDOWN_CAUSE_HOST_ERROR, + EXIT_FAILURE); } if (((uint32_t)kernel_entry & 0xFFu) != 0x80u) { diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 810f313988f9..343603d10216 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -15,6 +15,6 @@ riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) riscv_ss.add(when: 'CONFIG_RISCV_DEBUG', if_true: files('debug.c')) -riscv_ss.add(when: 'CONFIG_RISCV_DMI', if_true: files('dmi.c')) +riscv_ss.add(when: 'CONFIG_RISCV_DTM', if_true: files('dtm.c')) hw_arch += {'riscv': riscv_ss} diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index a8c67f2157cf..480fe1177eaf 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -67,101 +67,127 @@ #include "hw/opentitan/ot_timer.h" #include "hw/opentitan/ot_uart.h" #include "hw/qdev-properties.h" -#include "hw/riscv/dmi.h" +#include "hw/riscv/dtm.h" #include "hw/riscv/ibex_common.h" #include "hw/riscv/ot_darjeeling.h" #include "hw/ssi/ssi.h" #include "sysemu/blockdev.h" +#include "sysemu/reset.h" #include "sysemu/sysemu.h" /* ------------------------------------------------------------------------ */ /* Forward Declarations */ /* ------------------------------------------------------------------------ */ -static void ot_darjeeling_soc_hart_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); -static void ot_darjeeling_soc_otp_ctrl_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); -static void ot_darjeeling_soc_uart_configure( +static void ot_dj_soc_hart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent); +static void ot_dj_soc_otp_ctrl_configure( DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); +static void ot_dj_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent); /* ------------------------------------------------------------------------ */ /* Constants */ /* ------------------------------------------------------------------------ */ +enum OtDjMemoryRegion { + OT_DJ_DEFAULT_MEMORY_REGION, + OT_DJ_CTN_MEMORY_REGION, + OT_DJ_DEBUG_MEMORY_REGION, +}; -/* CTN address space */ -#define OT_DARJEELING_CTN_REGION_OFFSET 0x40000000u -#define OT_DARJEELING_CTN_REGION_SIZE (1u << 30u) - -/* CTN RAM (1MB) */ -#define OT_DARJEELING_CTN_RAM_ADDR 0x01000000u -#define OT_DARJEELING_CTN_RAM_SIZE (2u << 20u) - -enum OtDarjeelingSocDevice { - OT_DARJEELING_SOC_DEV_AES, - OT_DARJEELING_SOC_DEV_ALERT_HANDLER, - OT_DARJEELING_SOC_DEV_AON_TIMER, - OT_DARJEELING_SOC_DEV_AST, - OT_DARJEELING_SOC_DEV_CLKMGR, - OT_DARJEELING_SOC_DEV_CSRNG, - OT_DARJEELING_SOC_DEV_DM_TL_MBOX, - OT_DARJEELING_SOC_DEV_DMA, - OT_DARJEELING_SOC_DEV_DMI, - OT_DARJEELING_SOC_DEV_EDN0, - OT_DARJEELING_SOC_DEV_EDN1, - OT_DARJEELING_SOC_DEV_GPIO, - OT_DARJEELING_SOC_DEV_HART, - OT_DARJEELING_SOC_DEV_HMAC, - OT_DARJEELING_SOC_DEV_I2C0, - OT_DARJEELING_SOC_DEV_IBEX_WRAPPER, - OT_DARJEELING_SOC_DEV_KEYMGR_DPE, - OT_DARJEELING_SOC_DEV_KMAC, - OT_DARJEELING_SOC_DEV_LC_CTRL, - OT_DARJEELING_SOC_DEV_MBX0, - OT_DARJEELING_SOC_DEV_MBX1, - OT_DARJEELING_SOC_DEV_MBX2, - OT_DARJEELING_SOC_DEV_MBX3, - OT_DARJEELING_SOC_DEV_MBX4, - OT_DARJEELING_SOC_DEV_MBX5, - OT_DARJEELING_SOC_DEV_MBX6, - OT_DARJEELING_SOC_DEV_MBX_JTAG, - OT_DARJEELING_SOC_DEV_MBX_PCIE0, - OT_DARJEELING_SOC_DEV_MBX_PCIE1, - OT_DARJEELING_SOC_DEV_OTBN, - OT_DARJEELING_SOC_DEV_OTP_CTRL, - OT_DARJEELING_SOC_DEV_PINMUX, - OT_DARJEELING_SOC_DEV_PLIC, - OT_DARJEELING_SOC_DEV_PWRMGR, - OT_DARJEELING_SOC_DEV_ROM0, - OT_DARJEELING_SOC_DEV_ROM1, - OT_DARJEELING_SOC_DEV_RSTMGR, - OT_DARJEELING_SOC_DEV_RV_DM, - OT_DARJEELING_SOC_DEV_RV_DM_MEM, - OT_DARJEELING_SOC_DEV_SENSOR_CTRL, - OT_DARJEELING_SOC_DEV_SOC_PROXY, - OT_DARJEELING_SOC_DEV_SPI_DEVICE, - OT_DARJEELING_SOC_DEV_SPI_HOST0, - OT_DARJEELING_SOC_DEV_SRAM_MAIN, - OT_DARJEELING_SOC_DEV_SRAM_MBX, - OT_DARJEELING_SOC_DEV_SRAM_RET, - OT_DARJEELING_SOC_DEV_TIMER, - OT_DARJEELING_SOC_DEV_UART0, +enum OtDjSocDevice { + OT_DJ_SOC_DEV_AES, + OT_DJ_SOC_DEV_ALERT_HANDLER, + OT_DJ_SOC_DEV_AON_TIMER, + OT_DJ_SOC_DEV_AST, + OT_DJ_SOC_DEV_CLKMGR, + OT_DJ_SOC_DEV_CSRNG, + OT_DJ_SOC_DEV_DM_TL_LC_CTRL, + OT_DJ_SOC_DEV_DM_TL_MBX, + OT_DJ_SOC_DEV_DMA, + OT_DJ_SOC_DEV_DTM, + OT_DJ_SOC_DEV_EDN0, + OT_DJ_SOC_DEV_EDN1, + OT_DJ_SOC_DEV_GPIO, + OT_DJ_SOC_DEV_HART, + OT_DJ_SOC_DEV_HMAC, + OT_DJ_SOC_DEV_I2C0, + OT_DJ_SOC_DEV_IBEX_WRAPPER, + OT_DJ_SOC_DEV_KEYMGR_DPE, + OT_DJ_SOC_DEV_KMAC, + OT_DJ_SOC_DEV_LC_CTRL, + OT_DJ_SOC_DEV_MBX0, + OT_DJ_SOC_DEV_MBX1, + OT_DJ_SOC_DEV_MBX2, + OT_DJ_SOC_DEV_MBX3, + OT_DJ_SOC_DEV_MBX4, + OT_DJ_SOC_DEV_MBX5, + OT_DJ_SOC_DEV_MBX6, + OT_DJ_SOC_DEV_MBX_JTAG, + OT_DJ_SOC_DEV_MBX_PCIE0, + OT_DJ_SOC_DEV_MBX_PCIE1, + OT_DJ_SOC_DEV_OTBN, + OT_DJ_SOC_DEV_OTP_CTRL, + OT_DJ_SOC_DEV_PINMUX, + OT_DJ_SOC_DEV_PLIC, + OT_DJ_SOC_DEV_PWRMGR, + OT_DJ_SOC_DEV_ROM0, + OT_DJ_SOC_DEV_ROM1, + OT_DJ_SOC_DEV_RSTMGR, + OT_DJ_SOC_DEV_RV_DM, + OT_DJ_SOC_DEV_RV_DM_MEM, + OT_DJ_SOC_DEV_SENSOR_CTRL, + OT_DJ_SOC_DEV_SOC_PROXY, + OT_DJ_SOC_DEV_SPI_DEVICE, + OT_DJ_SOC_DEV_SPI_HOST0, + OT_DJ_SOC_DEV_SRAM_MAIN, + OT_DJ_SOC_DEV_SRAM_MBX, + OT_DJ_SOC_DEV_SRAM_RET, + OT_DJ_SOC_DEV_TIMER, + OT_DJ_SOC_DEV_UART0, /* IRQ splitters, i.e. 1-to-N signal dispatchers */ - OT_DARJEELING_SOC_SPLITTER_LC_HW_DEBUG, - OT_DARJEELING_SOC_SPLITTER_LC_ESCALATE, + OT_DJ_SOC_SPLITTER_LC_HW_DEBUG, + OT_DJ_SOC_SPLITTER_LC_ESCALATE, }; -/* Darjeeling Peripheral clock is 62.5 MHz */ -#define OT_DARJEELING_PERIPHERAL_CLK_HZ 62500000u +enum OtDjResetRequest { + OT_DJ_RESET_AON_TIMER, + OT_DJ_RESET_SOC_PROXY, + OT_DJ_RESET_COUNT, +}; -/* Darjeeling SPI host clock is 250 MHz */ -#define OT_DARJEELING__SPIHOST_CLK_HZ 250000000u +enum OtDjResetWakeup { + OT_DJ_WAKEUP_PINMUX_AON_PIN, + OT_DJ_WAKEUP_PINMUX_AON_USB, + OT_DJ_WAKEUP_AON_TIMER_AON, + OT_DJ_WAKEUP_SENSOR_CTRL, + OT_DJ_WAKEUP_SOC_PROXY_INTERNAL, + OT_DJ_WAKEUP_SOC_PROXY_EXTERNAL, + OT_DJ_WAKEUP_COUNT, +}; -/* Darjeeling AON clock is 62.5 MHz */ -#define OT_DARJEELING_AON_CLK_HZ 62500000u +/* CTN address space */ +#define OT_DJ_CTN_REGION_OFFSET 0x40000000u +#define OT_DJ_CTN_REGION_SIZE (1u << 30u) -static const uint8_t ot_darjeeling_pmp_cfgs[] = { +/* CTN RAM (1MB) */ +#define OT_DJ_CTN_RAM_ADDR 0x01000000u +#define OT_DJ_CTN_RAM_SIZE (2u << 20u) + +/* DEBUG address space */ +#define OT_DJ_DEBUG_RV_DM_ADDR 0x2000u +#define OT_DJ_DEBUG_MBX_JTAG_ADDR 0x2200u +#define OT_DJ_DEBUG_SOCDBG_CTRL_ADDR 0x2300u +#define OT_DJ_DEBUG_LC_CTRL_ADDR 0x3000u +#define OT_DJ_DEBUG_LC_CTRL_SIZE 0x400u +#define OT_DJ_DBG_XBAR_SIZE 0x4000u + +#define OT_DJ_PERIPHERAL_CLK_HZ 62500000u +#define OT_DJ_SPIHOST_CLK_HZ 250000000u +#define OT_DJ_AON_CLK_HZ 62500000u + +static const uint8_t ot_dj_pmp_cfgs[] = { /* clang-format off */ IBEX_PMP_CFG(0, IBEX_PMP_MODE_OFF, 0, 0, 0), IBEX_PMP_CFG(0, IBEX_PMP_MODE_OFF, 0, 0, 0), @@ -182,7 +208,7 @@ static const uint8_t ot_darjeeling_pmp_cfgs[] = { /* clang-format on */ }; -static const uint32_t ot_darjeeling_pmp_addrs[] = { +static const uint32_t ot_dj_pmp_addrs[] = { /* clang-format off */ IBEX_PMP_ADDR(0x00000000), IBEX_PMP_ADDR(0x00000000), @@ -203,25 +229,19 @@ static const uint32_t ot_darjeeling_pmp_addrs[] = { /* clang-format on */ }; -#define OT_DARJEELING_MSECCFG IBEX_MSECCFG(1, 1, 0) +#define OT_DJ_MSECCFG IBEX_MSECCFG(1, 1, 0) -enum OtDarjeelingMemoryRegion { - OT_DARJEELING_DEFAULT_MEMORY_REGION, - OT_DARJEELING_CTN_MEMORY_REGION, - OT_DARJEELING_DEBUG_MEMORY_REGION, -}; +#define OT_DJ_SOC_GPIO(_irq_, _target_, _num_) \ + IBEX_GPIO(_irq_, OT_DJ_SOC_DEV_##_target_, _num_) -#define OT_DARJEELING_SOC_GPIO(_irq_, _target_, _num_) \ - IBEX_GPIO(_irq_, OT_DARJEELING_SOC_DEV_##_target_, _num_) +#define OT_DJ_SOC_GPIO_SYSBUS_IRQ(_irq_, _target_, _num_) \ + IBEX_GPIO_SYSBUS_IRQ(_irq_, OT_DJ_SOC_DEV_##_target_, _num_) -#define OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(_irq_, _target_, _num_) \ - IBEX_GPIO_SYSBUS_IRQ(_irq_, OT_DARJEELING_SOC_DEV_##_target_, _num_) - -#define OT_DARJEELING_SOC_DEVLINK(_pname_, _target_) \ - IBEX_DEVLINK(_pname_, OT_DARJEELING_SOC_DEV_##_target_) +#define OT_DJ_SOC_DEVLINK(_pname_, _target_) \ + IBEX_DEVLINK(_pname_, OT_DJ_SOC_DEV_##_target_) /* Device named signal to device named signal */ -#define OT_DARJEELING_SOC_SIGNAL(_sname_, _snum_, _tgt_, _tname_, _tnum_) \ +#define OT_DJ_SOC_SIGNAL(_sname_, _snum_, _tgt_, _tname_, _tnum_) \ { \ .out = { \ .name = (_sname_), \ @@ -229,77 +249,81 @@ enum OtDarjeelingMemoryRegion { }, \ .in = { \ .name = (_tname_), \ - .index = (OT_DARJEELING_SOC_DEV_ ## _tgt_), \ + .index = (OT_DJ_SOC_DEV_ ## _tgt_), \ .num = (_tnum_), \ } \ } /* Device named signal to splitter input */ -#define OT_DARJEELING_SOC_D2S(_sname_, _snum_, _tgt_) \ +#define OT_DJ_SOC_D2S(_sname_, _snum_, _tgt_) \ { \ .out = { \ .name = (_sname_), \ .num = (_snum_), \ }, \ .in = { \ - .index = (OT_DARJEELING_SOC_SPLITTER_ ## _tgt_), \ + .index = (OT_DJ_SOC_SPLITTER_ ## _tgt_), \ } \ } /* Splitter output to device named signal */ -#define OT_DARJEELING_SOC_S2D(_snum_, _tgt_, _tname_, _tnum_) \ +#define OT_DJ_SOC_S2D(_snum_, _tgt_, _tname_, _tnum_) \ { \ .out = { \ .num = (_snum_), \ }, \ .in = { \ .name = (_tname_), \ - .index = (OT_DARJEELING_SOC_DEV_ ## _tgt_), \ + .index = (OT_DJ_SOC_DEV_ ## _tgt_), \ .num = (_tnum_), \ } \ } /* Request link */ -#define OT_DARJEELING_SOC_REQ(_req_, _tgt_) \ - OT_DARJEELING_SOC_SIGNAL(_req_##_REQ, 0, _tgt_, _req_##_REQ, 0) +#define OT_DJ_SOC_REQ(_req_, _tgt_) \ + OT_DJ_SOC_SIGNAL(_req_##_REQ, 0, _tgt_, _req_##_REQ, 0) /* Response link */ -#define OT_DARJEELING_SOC_RSP(_rsp_, _tgt_) \ - OT_DARJEELING_SOC_SIGNAL(_rsp_##_RSP, 0, _tgt_, _rsp_##_RSP, 0) +#define OT_DJ_SOC_RSP(_rsp_, _tgt_) \ + OT_DJ_SOC_SIGNAL(_rsp_##_RSP, 0, _tgt_, _rsp_##_RSP, 0) -#define OT_DARJEELING_SOC_DEV_MBX(_ix_, _addr_, _irq_) \ +#define OT_DJ_SOC_DEV_MBX(_ix_, _addr_, _irq_) \ .type = TYPE_OT_MBX, .instance = (_ix_), \ .memmap = MEMMAPENTRIES({ (_addr_), OT_MBX_HOST_APERTURE }), \ .gpio = \ - IBEXGPIOCONNDEFS(OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, (_irq_)), \ - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, \ - (_irq_) + 1u), \ - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, \ - (_irq_) + 2u)), \ + IBEXGPIOCONNDEFS(OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, (_irq_)), \ + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, (_irq_) + 1u), \ + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, (_irq_) + 2u)), \ .prop = IBEXDEVICEPROPDEFS(IBEX_DEV_STRING_PROP("ot_id", stringify(_ix_))) -#define OT_DARJEELING_SOC_DEV_MBX_DUAL(_ix_, _addr_, _irq_, _xaddr_) \ +#define OT_DJ_SOC_DEV_MBX_DUAL(_ix_, _addr_, _irq_, _xaddr_) \ .type = TYPE_OT_MBX, .instance = (_ix_), \ .memmap = MEMMAPENTRIES({ (_addr_), OT_MBX_HOST_APERTURE }, \ { (_xaddr_), OT_MBX_SYS_APERTURE }), \ .gpio = \ - IBEXGPIOCONNDEFS(OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, (_irq_)), \ - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, \ - (_irq_) + 1u), \ - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, \ - (_irq_) + 2u)), \ + IBEXGPIOCONNDEFS(OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, (_irq_)), \ + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, (_irq_) + 1u), \ + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, (_irq_) + 2u)), \ .prop = IBEXDEVICEPROPDEFS(IBEX_DEV_STRING_PROP("ot_id", stringify(_ix_))) -#define OT_DARJEELING_SOC_CLKMGR_HINT(_num_) \ - OT_DARJEELING_SOC_SIGNAL(OT_CLOCK_ACTIVE, 0, CLKMGR, OT_CLKMGR_HINT, _num_) - -#define OT_DARJEELING_XPORT_MEMORY(_addr_) \ - IBEX_MEMMAP_MAKE_REG((_addr_), OT_DARJEELING_CTN_MEMORY_REGION) +#define OT_DJ_SOC_CLKMGR_HINT(_num_) \ + OT_DJ_SOC_SIGNAL(OT_CLOCK_ACTIVE, 0, CLKMGR, OT_CLKMGR_HINT, _num_) -#define OT_DARJEELING_DBG_XBAR_APERTURE 0x2000u +#define OT_DJ_XPORT_MEMORY(_addr_) \ + IBEX_MEMMAP_MAKE_REG((_addr_), OT_DJ_CTN_MEMORY_REGION) #define DEBUG_MEMORY(_addr_) \ - IBEX_MEMMAP_MAKE_REG((_addr_), OT_DARJEELING_DEBUG_MEMORY_REGION) + IBEX_MEMMAP_MAKE_REG((_addr_), OT_DJ_DEBUG_MEMORY_REGION) + +#define OT_DJ_DEBUG_TL_TO_DMI(_val_) ((_val_) / sizeof(uint32_t)) + +#define OT_DJ_DEBUG_LC_CTRL_DMI_ADDR \ + OT_DJ_DEBUG_TL_TO_DMI(OT_DJ_DEBUG_LC_CTRL_ADDR) +#define OT_DJ_DEBUG_LC_CTRL_DMI_SIZE \ + OT_DJ_DEBUG_TL_TO_DMI(OT_DJ_DEBUG_LC_CTRL_SIZE) +#define OT_DJ_DEBUG_MBX_JTAG_DMI_ADDR \ + OT_DJ_DEBUG_TL_TO_DMI(OT_DJ_DEBUG_MBX_JTAG_ADDR) +#define OT_DJ_DEBUG_MBX_JTAG_DMI_SIZE (OT_MBX_SYS_APERTURE / sizeof(uint32_t)) /* * Darjeeling RV DM @@ -313,11 +337,11 @@ enum OtDarjeelingMemoryRegion { * and * lowRISC/opentitan: hw/top_darjeeling/sw/autogen/top_darjeeling.h */ -static const IbexDeviceDef ot_darjeeling_soc_devices[] = { +static const IbexDeviceDef ot_dj_soc_devices[] = { /* clang-format off */ - [OT_DARJEELING_SOC_DEV_HART] = { + [OT_DJ_SOC_DEV_HART] = { .type = TYPE_RISCV_CPU_LOWRISC_IBEX, - .cfg = &ot_darjeeling_soc_hart_configure, + .cfg = &ot_dj_soc_hart_configure, .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_BOOL_PROP("m", true), IBEX_DEV_BOOL_PROP("pmp", true), @@ -332,90 +356,104 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { IBEX_DEV_BOOL_PROP("start-powered-off", true) ), }, - [OT_DARJEELING_SOC_DEV_DMI] = { - .type = TYPE_RISCV_DMI, + [OT_DJ_SOC_DEV_DTM] = { + .type = TYPE_RISCV_DTM, .prop = IBEXDEVICEPROPDEFS( - /* should be a constant, need to encode 0x500 */ - IBEX_DEV_UINT_PROP("abits", 11u) + IBEX_DEV_UINT_PROP("abits", 12u) + ), + }, + [OT_DJ_SOC_DEV_DM_TL_LC_CTRL] = { + .type = TYPE_OT_DM_TL, + .instance = 0, + .link = IBEXDEVICELINKDEFS( + OT_DJ_SOC_DEVLINK("dtm", DTM), + OT_DJ_SOC_DEVLINK("tl_dev", LC_CTRL) ), + .prop = IBEXDEVICEPROPDEFS( + IBEX_DEV_UINT_PROP("dmi_addr", OT_DJ_DEBUG_LC_CTRL_DMI_ADDR), + IBEX_DEV_UINT_PROP("dmi_size", OT_DJ_DEBUG_LC_CTRL_DMI_SIZE), + IBEX_DEV_UINT_PROP("tl_addr", OT_DJ_DEBUG_LC_CTRL_ADDR), + IBEX_DEV_STRING_PROP("tl_as_name", "ot-dbg") + ) }, - [OT_DARJEELING_SOC_DEV_DM_TL_MBOX] = { + [OT_DJ_SOC_DEV_DM_TL_MBX] = { .type = TYPE_OT_DM_TL, + .instance = 1, .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("dmi", DMI), - OT_DARJEELING_SOC_DEVLINK("tl_dev", MBX_JTAG) + OT_DJ_SOC_DEVLINK("dtm", DTM), + OT_DJ_SOC_DEVLINK("tl_dev", MBX_JTAG) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("dmi_addr", 0x400u), - IBEX_DEV_UINT_PROP("dmi_size", OT_MBX_SYS_REGS_COUNT), - IBEX_DEV_UINT_PROP("tl_addr", 0x1000u), + IBEX_DEV_UINT_PROP("dmi_addr", OT_DJ_DEBUG_MBX_JTAG_DMI_ADDR), + IBEX_DEV_UINT_PROP("dmi_size", OT_DJ_DEBUG_MBX_JTAG_DMI_SIZE), + IBEX_DEV_UINT_PROP("tl_addr", OT_DJ_DEBUG_MBX_JTAG_ADDR), IBEX_DEV_STRING_PROP("tl_as_name", "ot-dbg") ) }, - [OT_DARJEELING_SOC_DEV_AES] = { + [OT_DJ_SOC_DEV_AES] = { .type = TYPE_OT_AES, .memmap = MEMMAPENTRIES( { 0x21100000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_AES) + OT_DJ_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_AES) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("edn", EDN0) + OT_DJ_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 5u) ), }, - [OT_DARJEELING_SOC_DEV_HMAC] = { + [OT_DJ_SOC_DEV_HMAC] = { .type = TYPE_OT_HMAC, .memmap = MEMMAPENTRIES( { 0x21110000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 115), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 116), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 117), - OT_DARJEELING_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_HMAC) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 115), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 116), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 117), + OT_DJ_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_HMAC) ), }, - [OT_DARJEELING_SOC_DEV_KMAC] = { + [OT_DJ_SOC_DEV_KMAC] = { .type = TYPE_OT_KMAC, .memmap = MEMMAPENTRIES( { 0x21120000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 118), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 119), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 120) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 118), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 119), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 120) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("edn", EDN0) + OT_DJ_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 3u), IBEX_DEV_UINT_PROP("num-app", 4u) ), }, - [OT_DARJEELING_SOC_DEV_OTBN] = { + [OT_DJ_SOC_DEV_OTBN] = { .type = TYPE_OT_OTBN, .memmap = MEMMAPENTRIES( { 0x21130000u, 0x10000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 121), - OT_DARJEELING_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_OTBN) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 121), + OT_DJ_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_OTBN) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("edn-u", EDN0), - OT_DARJEELING_SOC_DEVLINK("edn-r", EDN1) + OT_DJ_SOC_DEVLINK("edn-u", EDN0), + OT_DJ_SOC_DEVLINK("edn-r", EDN1) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-u-ep", 6u), IBEX_DEV_UINT_PROP("edn-r-ep", 0u) ), }, - [OT_DARJEELING_SOC_DEV_KEYMGR_DPE] = { + [OT_DJ_SOC_DEV_KEYMGR_DPE] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-keymgr_dpe", .cfg = &ibex_unimp_configure, @@ -423,57 +461,57 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x21140000u, 0x100u } ), }, - [OT_DARJEELING_SOC_DEV_CSRNG] = { + [OT_DJ_SOC_DEV_CSRNG] = { .type = TYPE_OT_CSRNG, .memmap = MEMMAPENTRIES( { 0x21150000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 123), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 124), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 125), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 126) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 123), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 124), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 125), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 126) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("random_src", AST), - OT_DARJEELING_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("random_src", AST), + OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), }, - [OT_DARJEELING_SOC_DEV_EDN0] = { + [OT_DJ_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, .instance = 0, .memmap = MEMMAPENTRIES( { 0x21170000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 127), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 128) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 127), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 128) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("csrng", CSRNG) + OT_DJ_SOC_DEVLINK("csrng", CSRNG) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("csrng-app", 0) ), }, - [OT_DARJEELING_SOC_DEV_EDN1] = { + [OT_DJ_SOC_DEV_EDN1] = { .type = TYPE_OT_EDN, .instance = 1, .memmap = MEMMAPENTRIES( { 0x21180000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 129), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 130) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 129), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 130) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("csrng", CSRNG) + OT_DJ_SOC_DEVLINK("csrng", CSRNG) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("csrng-app", 1u) ), }, - [OT_DARJEELING_SOC_DEV_SRAM_MAIN] = { + [OT_DJ_SOC_DEV_SRAM_MAIN] = { .type = TYPE_OT_SRAM_CTRL, .instance = 0, .memmap = MEMMAPENTRIES( @@ -481,14 +519,14 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x10000000, 0x10000u } ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("size", 0x10000u), IBEX_DEV_STRING_PROP("ot_id", "ram") ), }, - [OT_DARJEELING_SOC_DEV_SRAM_MBX] = { + [OT_DJ_SOC_DEV_SRAM_MBX] = { .type = TYPE_OT_SRAM_CTRL, .instance = 1, .memmap = MEMMAPENTRIES( @@ -496,14 +534,14 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x11000000u, 0x1000u } ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("size", 0x1000u), IBEX_DEV_STRING_PROP("ot_id", "mbx") ), }, - [OT_DARJEELING_SOC_DEV_ROM0] = { + [OT_DJ_SOC_DEV_ROM0] = { .type = TYPE_OT_ROM_CTRL, .instance = 0, .memmap = MEMMAPENTRIES( @@ -511,13 +549,13 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x00008000u, 0x8000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, + OT_DJ_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, OT_PWRMGR_ROM_GOOD, 0), - OT_DARJEELING_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, + OT_DJ_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, OT_PWRMGR_ROM_DONE, 0) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("kmac", KMAC) + OT_DJ_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("ot_id", "rom0"), @@ -525,7 +563,7 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { IBEX_DEV_UINT_PROP("kmac-app", 2u) ), }, - [OT_DARJEELING_SOC_DEV_ROM1] = { + [OT_DJ_SOC_DEV_ROM1] = { .type = TYPE_OT_ROM_CTRL, .instance = 1, .memmap = MEMMAPENTRIES( @@ -533,13 +571,13 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x00020000u, 0x10000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, + OT_DJ_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, OT_PWRMGR_ROM_GOOD, 1), - OT_DARJEELING_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, + OT_DJ_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, OT_PWRMGR_ROM_DONE, 1) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("kmac", KMAC) + OT_DJ_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("ot_id", "rom1"), @@ -547,19 +585,19 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { IBEX_DEV_UINT_PROP("kmac-app", 3u) ), }, - [OT_DARJEELING_SOC_DEV_IBEX_WRAPPER] = { + [OT_DJ_SOC_DEV_IBEX_WRAPPER] = { .type = TYPE_OT_IBEX_WRAPPER_DJ, .memmap = MEMMAPENTRIES( { 0x211f0000u, 0x800u } ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("edn", EDN0) + OT_DJ_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 7u) ), }, - [OT_DARJEELING_SOC_DEV_RV_DM] = { + [OT_DJ_SOC_DEV_RV_DM] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-rv_dm", .cfg = &ibex_unimp_configure, @@ -567,40 +605,40 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x21200000u, 0x1000u } ), }, - [OT_DARJEELING_SOC_DEV_MBX0] = { - OT_DARJEELING_SOC_DEV_MBX(0, 0x22000000u, 134), + [OT_DJ_SOC_DEV_MBX0] = { + OT_DJ_SOC_DEV_MBX(0, 0x22000000u, 134), }, - [OT_DARJEELING_SOC_DEV_MBX1] = { - OT_DARJEELING_SOC_DEV_MBX(1, 0x22000100u, 137), + [OT_DJ_SOC_DEV_MBX1] = { + OT_DJ_SOC_DEV_MBX(1, 0x22000100u, 137), }, - [OT_DARJEELING_SOC_DEV_MBX2] = { - OT_DARJEELING_SOC_DEV_MBX(2, 0x22000200u, 140), + [OT_DJ_SOC_DEV_MBX2] = { + OT_DJ_SOC_DEV_MBX(2, 0x22000200u, 140), }, - [OT_DARJEELING_SOC_DEV_MBX3] = { - OT_DARJEELING_SOC_DEV_MBX(3, 0x22000300u, 143), + [OT_DJ_SOC_DEV_MBX3] = { + OT_DJ_SOC_DEV_MBX(3, 0x22000300u, 143), }, - [OT_DARJEELING_SOC_DEV_MBX4] = { - OT_DARJEELING_SOC_DEV_MBX(4, 0x22000400u, 146), + [OT_DJ_SOC_DEV_MBX4] = { + OT_DJ_SOC_DEV_MBX(4, 0x22000400u, 146), }, - [OT_DARJEELING_SOC_DEV_MBX5] = { - OT_DARJEELING_SOC_DEV_MBX(5, 0x22000500u, 149), + [OT_DJ_SOC_DEV_MBX5] = { + OT_DJ_SOC_DEV_MBX(5, 0x22000500u, 149), }, - [OT_DARJEELING_SOC_DEV_MBX6] = { - OT_DARJEELING_SOC_DEV_MBX(6, 0x22000600u, 152), + [OT_DJ_SOC_DEV_MBX6] = { + OT_DJ_SOC_DEV_MBX(6, 0x22000600u, 152), }, - [OT_DARJEELING_SOC_DEV_MBX_JTAG] = { - OT_DARJEELING_SOC_DEV_MBX_DUAL(7, 0x22000800u, 155, - DEBUG_MEMORY(0x1000)), + [OT_DJ_SOC_DEV_MBX_JTAG] = { + OT_DJ_SOC_DEV_MBX_DUAL(7, 0x22000800u, 155, + DEBUG_MEMORY(OT_DJ_DEBUG_MBX_JTAG_ADDR)), }, - [OT_DARJEELING_SOC_DEV_DMA] = { + [OT_DJ_SOC_DEV_DMA] = { .type = TYPE_OT_DMA, .memmap = MEMMAPENTRIES( { 0x22010000u, 0x200u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 131), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 132), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 133) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 131), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 132), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 133) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("ot_id", "0"), @@ -609,62 +647,62 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { ) }, - [OT_DARJEELING_SOC_DEV_SOC_PROXY] = { + [OT_DJ_SOC_DEV_SOC_PROXY] = { .type = TYPE_OT_SOC_PROXY, .memmap = MEMMAPENTRIES( { 0x22030000u, 0x10u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 83), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 84), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 85), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 86), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 87), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 88), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 89), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 90), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 91), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 92), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 93), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 94), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(12, PLIC, 95), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(13, PLIC, 96), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(14, PLIC, 97), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(15, PLIC, 98), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(16, PLIC, 99), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(17, PLIC, 100), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(18, PLIC, 101), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(19, PLIC, 102), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(20, PLIC, 103), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(21, PLIC, 104), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(22, PLIC, 105), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(23, PLIC, 106), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(24, PLIC, 107), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(25, PLIC, 108), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(26, PLIC, 109), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(27, PLIC, 110), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 111), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 112), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 113), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 114) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 83), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 84), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 85), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 86), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 87), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 88), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 89), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 90), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 91), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 92), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 93), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 94), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(12, PLIC, 95), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(13, PLIC, 96), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(14, PLIC, 97), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(15, PLIC, 98), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(16, PLIC, 99), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(17, PLIC, 100), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(18, PLIC, 101), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(19, PLIC, 102), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(20, PLIC, 103), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(21, PLIC, 104), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(22, PLIC, 105), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(23, PLIC, 106), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(24, PLIC, 107), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(25, PLIC, 108), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(26, PLIC, 109), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(27, PLIC, 110), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 111), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 112), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 113), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 114) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("ot_id", "0") ), }, - [OT_DARJEELING_SOC_DEV_MBX_PCIE0] = { - OT_DARJEELING_SOC_DEV_MBX(8, 0x22040000u, 158), + [OT_DJ_SOC_DEV_MBX_PCIE0] = { + OT_DJ_SOC_DEV_MBX(8, 0x22040000u, 158), }, - [OT_DARJEELING_SOC_DEV_MBX_PCIE1] = { - OT_DARJEELING_SOC_DEV_MBX(9, 0x22040100u, 161), + [OT_DJ_SOC_DEV_MBX_PCIE1] = { + OT_DJ_SOC_DEV_MBX(9, 0x22040100u, 161), }, - [OT_DARJEELING_SOC_DEV_PLIC] = { + [OT_DJ_SOC_DEV_PLIC] = { .type = TYPE_SIFIVE_PLIC, .memmap = MEMMAPENTRIES( { 0x28000000u, 0x8000000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO(1, HART, IRQ_M_EXT) + OT_DJ_SOC_GPIO(1, HART, IRQ_M_EXT) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("hart-config", "M"), @@ -681,79 +719,79 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { IBEX_DEV_UINT_PROP("aperture-size", 0x8000000u) ), }, - [OT_DARJEELING_SOC_DEV_GPIO] = { + [OT_DJ_SOC_DEV_GPIO] = { .type = TYPE_OT_GPIO, .name = "ot-gpio", .memmap = MEMMAPENTRIES( { 0x30000000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 9), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 10), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 11), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 12), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 13), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 14), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 15), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 16), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 17), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 18), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 19), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 20), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(12, PLIC, 21), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(13, PLIC, 22), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(14, PLIC, 23), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(15, PLIC, 24), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(16, PLIC, 25), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(17, PLIC, 26), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(18, PLIC, 27), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(19, PLIC, 28), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(20, PLIC, 29), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(21, PLIC, 30), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(22, PLIC, 31), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(23, PLIC, 32), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(24, PLIC, 33), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(25, PLIC, 34), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(26, PLIC, 35), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(27, PLIC, 36), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 37), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 38), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 39), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 40) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 9), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 10), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 11), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 12), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 13), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 14), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 15), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 16), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 17), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 18), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 19), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 20), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(12, PLIC, 21), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(13, PLIC, 22), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(14, PLIC, 23), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(15, PLIC, 24), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(16, PLIC, 25), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(17, PLIC, 26), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(18, PLIC, 27), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(19, PLIC, 28), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(20, PLIC, 29), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(21, PLIC, 30), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(22, PLIC, 31), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(23, PLIC, 32), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(24, PLIC, 33), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(25, PLIC, 34), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(26, PLIC, 35), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(27, PLIC, 36), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 37), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 38), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 39), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 40) ) }, - [OT_DARJEELING_SOC_DEV_UART0] = { + [OT_DJ_SOC_DEV_UART0] = { .type = TYPE_OT_UART, - .cfg = &ot_darjeeling_soc_uart_configure, + .cfg = &ot_dj_soc_uart_configure, .instance = 0, .memmap = MEMMAPENTRIES( { 0x30010000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 1), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 2), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 3), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 4), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 5), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 6), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 7), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 8) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 1), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 2), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 3), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 4), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 5), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 6), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 7), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 8) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_DARJEELING_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_DJ_PERIPHERAL_CLK_HZ) ), }, - [OT_DARJEELING_SOC_DEV_SENSOR_CTRL] = { + [OT_DJ_SOC_DEV_SENSOR_CTRL] = { .type = TYPE_OT_SENSOR, .memmap = MEMMAPENTRIES( { 0x30020000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 81), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 82) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 81), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 82) ) }, - [OT_DARJEELING_SOC_DEV_I2C0] = { + [OT_DJ_SOC_DEV_I2C0] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, @@ -762,69 +800,70 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x30080000u, 0x80u } ), }, - [OT_DARJEELING_SOC_DEV_TIMER] = { + [OT_DJ_SOC_DEV_TIMER] = { .type = TYPE_OT_TIMER, .memmap = MEMMAPENTRIES( { 0x30100000u, 0x200u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO(0, HART, IRQ_M_TIMER), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 68) + OT_DJ_SOC_GPIO(0, HART, IRQ_M_TIMER), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 68) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_DARJEELING_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_DJ_PERIPHERAL_CLK_HZ) ), }, - [OT_DARJEELING_SOC_DEV_OTP_CTRL] = { + [OT_DJ_SOC_DEV_OTP_CTRL] = { .type = TYPE_OT_OTP_DJ, - .cfg = &ot_darjeeling_soc_otp_ctrl_configure, + .cfg = &ot_dj_soc_otp_ctrl_configure, .memmap = MEMMAPENTRIES( { 0x30130000u, 0x8000u }, { 0x30138000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 69), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 70), - OT_DARJEELING_SOC_RSP(OT_PWRMGR_OTP, PWRMGR) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 69), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 70), + OT_DJ_SOC_RSP(OT_PWRMGR_OTP, PWRMGR) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("edn", EDN0) + OT_DJ_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 1u) ), }, - [OT_DARJEELING_SOC_DEV_LC_CTRL] = { + [OT_DJ_SOC_DEV_LC_CTRL] = { .type = TYPE_OT_LC_CTRL, .memmap = MEMMAPENTRIES( - { 0x30140000u, 0x100u } + { 0x30140000u, 0x100u }, + { DEBUG_MEMORY(OT_DJ_DEBUG_LC_CTRL_ADDR), OT_DJ_DEBUG_LC_CTRL_SIZE } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_D2S(OT_LC_BROADCAST, OT_LC_HW_DEBUG_EN, + OT_DJ_SOC_D2S(OT_LC_BROADCAST, OT_LC_HW_DEBUG_EN, LC_HW_DEBUG), - OT_DARJEELING_SOC_D2S(OT_LC_BROADCAST, OT_LC_ESCALATE_EN, + OT_DJ_SOC_D2S(OT_LC_BROADCAST, OT_LC_ESCALATE_EN, LC_ESCALATE), - OT_DARJEELING_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_CPU_EN, + OT_DJ_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_CPU_EN, IBEX_WRAPPER, OT_IBEX_WRAPPER_CPU_EN, OT_IBEX_LC_CTRL_CPU_EN), - OT_DARJEELING_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_CHECK_BYP_EN, + OT_DJ_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_CHECK_BYP_EN, OTP_CTRL, OT_LC_BROADCAST, OT_OTP_LC_CHECK_BYP_EN), - OT_DARJEELING_SOC_SIGNAL(OT_LC_BROADCAST, + OT_DJ_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_CREATOR_SEED_SW_RW_EN, OTP_CTRL, OT_LC_BROADCAST, OT_OTP_LC_CREATOR_SEED_SW_RW_EN), - OT_DARJEELING_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_OWNER_SEED_SW_RW_EN, + OT_DJ_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_OWNER_SEED_SW_RW_EN, OTP_CTRL, OT_LC_BROADCAST, OT_OTP_LC_OWNER_SEED_SW_RW_EN), - OT_DARJEELING_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_SEED_HW_RD_EN, + OT_DJ_SOC_SIGNAL(OT_LC_BROADCAST, OT_LC_SEED_HW_RD_EN, OTP_CTRL, OT_LC_BROADCAST, OT_OTP_LC_SEED_HW_RD_EN), - OT_DARJEELING_SOC_RSP(OT_PWRMGR_LC, PWRMGR) + OT_DJ_SOC_RSP(OT_PWRMGR_LC, PWRMGR) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("otp_ctrl", OTP_CTRL), - OT_DARJEELING_SOC_DEVLINK("kmac", KMAC) + OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_DJ_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("silicon_creator_id", 0x4002u), @@ -834,126 +873,125 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { IBEX_DEV_UINT_PROP("kmac-app", 1u) ) }, - [OT_DARJEELING_SOC_DEV_ALERT_HANDLER] = { + [OT_DJ_SOC_DEV_ALERT_HANDLER] = { .type = TYPE_OT_ALERT_DJ, .memmap = MEMMAPENTRIES( { 0x30150000u, 0x800u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 71), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 72), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 73), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 74) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 71), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 72), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 73), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 74) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("edn", EDN0) + OT_DJ_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 4u) ), }, - [OT_DARJEELING_SOC_DEV_SPI_HOST0] = { + [OT_DJ_SOC_DEV_SPI_HOST0] = { .type = TYPE_OT_SPI_HOST, .instance = 0, .memmap = MEMMAPENTRIES( { 0x30300000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 76), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 77) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 76), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 77) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("bus-num", 0) ), }, - [OT_DARJEELING_SOC_DEV_SPI_DEVICE] = { + [OT_DJ_SOC_DEV_SPI_DEVICE] = { .type = TYPE_OT_SPI_DEVICE, .memmap = MEMMAPENTRIES( { 0x30310000u, 0x2000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 41), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 42), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 43), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 44), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 45), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 46), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 47), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 48), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 49), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 50), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 51), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 52) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 41), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 42), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 43), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 44), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 45), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 46), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 47), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 48), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 49), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 50), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 51), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 52) ), }, - [OT_DARJEELING_SOC_DEV_PWRMGR] = { + [OT_DJ_SOC_DEV_PWRMGR] = { .type = TYPE_OT_PWRMGR, .memmap = MEMMAPENTRIES( { 0x30400000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 78), - OT_DARJEELING_SOC_REQ(OT_PWRMGR_OTP, OTP_CTRL), - OT_DARJEELING_SOC_REQ(OT_PWRMGR_LC, LC_CTRL), - OT_DARJEELING_SOC_SIGNAL(OT_PWRMGR_CPU_EN, 0, IBEX_WRAPPER, + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 78), + OT_DJ_SOC_REQ(OT_PWRMGR_OTP, OTP_CTRL), + OT_DJ_SOC_REQ(OT_PWRMGR_LC, LC_CTRL), + OT_DJ_SOC_SIGNAL(OT_PWRMGR_CPU_EN, 0, IBEX_WRAPPER, OT_IBEX_WRAPPER_CPU_EN, OT_IBEX_PWRMGR_CPU_EN) ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("rstmgr", RSTMGR) + OT_DJ_SOC_DEVLINK("rstmgr", RSTMGR) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("num-rom", 2u) + IBEX_DEV_UINT_PROP("num-rom", 2u), + IBEX_DEV_UINT_PROP("version", OT_PWMGR_VERSION_DJ) ), }, - [OT_DARJEELING_SOC_DEV_RSTMGR] = { + [OT_DJ_SOC_DEV_RSTMGR] = { .type = TYPE_OT_RSTMGR, .memmap = MEMMAPENTRIES( { 0x30410000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_SIGNAL(OT_RSTMGR_SW_RST, 0, PWRMGR, + OT_DJ_SOC_SIGNAL(OT_RSTMGR_SW_RST, 0, PWRMGR, OT_PWRMGR_SW_RST, 0) ), }, - [OT_DARJEELING_SOC_DEV_CLKMGR] = { + [OT_DJ_SOC_DEV_CLKMGR] = { .type = TYPE_OT_CLKMGR, .memmap = MEMMAPENTRIES( { 0x30420000u, 0x80u } ), }, - [OT_DARJEELING_SOC_DEV_PINMUX] = { + [OT_DJ_SOC_DEV_PINMUX] = { .type = TYPE_OT_PINMUX, .memmap = MEMMAPENTRIES( { 0x30460000u, 0x1000u } ), }, - [OT_DARJEELING_SOC_DEV_AON_TIMER] = { + [OT_DJ_SOC_DEV_AON_TIMER] = { .type = TYPE_OT_AON_TIMER, .memmap = MEMMAPENTRIES( { 0x30470000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 79), - OT_DARJEELING_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 80), - OT_DARJEELING_SOC_SIGNAL(OT_AON_TIMER_WKUP, 0, PWRMGR, - OT_PWRMGR_WKUP, - OT_PWRMGR_WAKEUP_AON_TIMER), - OT_DARJEELING_SOC_SIGNAL(OT_AON_TIMER_BITE, 0, PWRMGR, - OT_PWRMGR_RST, - OT_PWRMGR_RST_AON_TIMER) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 79), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 80), + OT_DJ_SOC_SIGNAL(OT_AON_TIMER_WKUP, 0, PWRMGR, + OT_PWRMGR_WKUP, OT_PWRMGR_WAKEUP_AON_TIMER), + OT_DJ_SOC_SIGNAL(OT_AON_TIMER_BITE, 0, PWRMGR, + OT_PWRMGR_RST, OT_DJ_RESET_AON_TIMER) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_DARJEELING_AON_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_DJ_AON_CLK_HZ) ), }, - [OT_DARJEELING_SOC_DEV_AST] = { + [OT_DJ_SOC_DEV_AST] = { .type = TYPE_OT_AST_DJ, .memmap = MEMMAPENTRIES( { 0x30480000u, 0x400u } ), }, - [OT_DARJEELING_SOC_DEV_SRAM_RET] = { + [OT_DJ_SOC_DEV_SRAM_RET] = { .type = TYPE_OT_SRAM_CTRL, .instance = 2, .memmap = MEMMAPENTRIES( @@ -961,7 +999,7 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { { 0x30600000u, 0x1000u } ), .link = IBEXDEVICELINKDEFS( - OT_DARJEELING_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("size", 0x1000u), @@ -969,18 +1007,18 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { ), }, /* IRQ splitters */ - [OT_DARJEELING_SOC_SPLITTER_LC_HW_DEBUG] = { + [OT_DJ_SOC_SPLITTER_LC_HW_DEBUG] = { .type = TYPE_SPLIT_IRQ, .instance = 0, .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("num-lines", 1u) // to be changed ) }, - [OT_DARJEELING_SOC_SPLITTER_LC_ESCALATE] = { + [OT_DJ_SOC_SPLITTER_LC_ESCALATE] = { .type = TYPE_SPLIT_IRQ, .instance = 1, .gpio = IBEXGPIOCONNDEFS( - OT_DARJEELING_SOC_S2D(0, OTP_CTRL, OT_LC_BROADCAST, + OT_DJ_SOC_S2D(0, OTP_CTRL, OT_LC_BROADCAST, OT_OTP_LC_ESCALATE_EN) ), .prop = IBEXDEVICEPROPDEFS( @@ -990,38 +1028,40 @@ static const IbexDeviceDef ot_darjeeling_soc_devices[] = { /* clang-format on */ }; -enum OtDarjeelingBoardDevice { - OT_DARJEELING_BOARD_DEV_SOC, - OT_DARJEELING_BOARD_DEV_FLASH, - OT_DARJEELING_BOARD_DEV_DEV_PROXY, - _OT_DARJEELING_BOARD_DEV_COUNT, +enum OtDjBoardDevice { + OT_DJ_BOARD_DEV_SOC, + OT_DJ_BOARD_DEV_FLASH, + OT_DJ_BOARD_DEV_DEV_PROXY, + OT_DJ_BOARD_DEV_COUNT, }; /* ------------------------------------------------------------------------ */ /* Type definitions */ /* ------------------------------------------------------------------------ */ -struct OtDarjeelingSoCClass { +struct OtDjSoCClass { DeviceClass parent_class; DeviceRealize parent_realize; ResettablePhases parent_phases; }; -struct OtDarjeelingSoCState { +struct OtDjSoCState { SysBusDevice parent_obj; DeviceState **devices; }; -struct OtDarjeelingBoardState { +struct OtDjBoardState { DeviceState parent_obj; DeviceState **devices; }; -struct OtDarjeelingMachineState { +struct OtDjMachineState { MachineState parent_obj; + ResettableState reset; + bool no_epmp_cfg; }; @@ -1029,11 +1069,10 @@ struct OtDarjeelingMachineState { /* Device Configuration */ /* ------------------------------------------------------------------------ */ -static void ot_darjeeling_soc_hart_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) +static void ot_dj_soc_hart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent) { - OtDarjeelingMachineState *ms = - RISCV_OT_DARJEELING_MACHINE(qdev_get_machine()); + OtDjMachineState *ms = RISCV_OT_DJ_MACHINE(qdev_get_machine()); QList *pmp_cfg, *pmp_addr; (void)def; (void)parent; @@ -1044,21 +1083,21 @@ static void ot_darjeeling_soc_hart_configure( } pmp_cfg = qlist_new(); - for (unsigned ix = 0; ix < ARRAY_SIZE(ot_darjeeling_pmp_cfgs); ix++) { - qlist_append_int(pmp_cfg, ot_darjeeling_pmp_cfgs[ix]); + for (unsigned ix = 0; ix < ARRAY_SIZE(ot_dj_pmp_cfgs); ix++) { + qlist_append_int(pmp_cfg, ot_dj_pmp_cfgs[ix]); } qdev_prop_set_array(dev, "pmp_cfg", pmp_cfg); pmp_addr = qlist_new(); - for (unsigned ix = 0; ix < ARRAY_SIZE(ot_darjeeling_pmp_addrs); ix++) { - qlist_append_int(pmp_addr, ot_darjeeling_pmp_addrs[ix]); + for (unsigned ix = 0; ix < ARRAY_SIZE(ot_dj_pmp_addrs); ix++) { + qlist_append_int(pmp_addr, ot_dj_pmp_addrs[ix]); } qdev_prop_set_array(dev, "pmp_addr", pmp_addr); - qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_DARJEELING_MSECCFG); + qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_DJ_MSECCFG); } -static void ot_darjeeling_soc_otp_ctrl_configure( +static void ot_dj_soc_otp_ctrl_configure( DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) { DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); @@ -1070,8 +1109,8 @@ static void ot_darjeeling_soc_otp_ctrl_configure( } } -static void ot_darjeeling_soc_uart_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) +static void ot_dj_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent) { (void)def; (void)parent; @@ -1082,64 +1121,71 @@ static void ot_darjeeling_soc_uart_configure( /* SoC */ /* ------------------------------------------------------------------------ */ -static void ot_darjeeling_soc_reset_hold(Object *obj) +static void ot_dj_soc_reset_hold(Object *obj) { - OtDarjeelingSoCClass *c = RISCV_OT_DARJEELING_SOC_GET_CLASS(obj); - OtDarjeelingSoCState *s = RISCV_OT_DARJEELING_SOC(obj); + OtDjSoCClass *c = RISCV_OT_DJ_SOC_GET_CLASS(obj); + OtDjSoCState *s = RISCV_OT_DJ_SOC(obj); if (c->parent_phases.hold) { c->parent_phases.hold(obj); } - Object *dmi = OBJECT(s->devices[OT_DARJEELING_SOC_DEV_DMI]); + Object *dmi = OBJECT(s->devices[OT_DJ_SOC_DEV_DTM]); resettable_reset(dmi, RESET_TYPE_COLD); - resettable_reset(OBJECT(s->devices[OT_DARJEELING_SOC_DEV_DM_TL_MBOX]), + // TODO: not sure where Reset is plugged here... + resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_TL_LC_CTRL]), + RESET_TYPE_COLD); + resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_TL_MBX]), RESET_TYPE_COLD); /* keep ROM_CTRLs in reset, we'll release them last */ - resettable_assert_reset(OBJECT(s->devices[OT_DARJEELING_SOC_DEV_ROM0]), + resettable_assert_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_ROM0]), RESET_TYPE_COLD); - resettable_assert_reset(OBJECT(s->devices[OT_DARJEELING_SOC_DEV_ROM1]), + resettable_assert_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_ROM1]), RESET_TYPE_COLD); /* - * leave hart on reset - * power manager should release it once ROMs have been validated + * Power-On-Reset: leave hart on reset + * PowerManager takes care of managing Ibex reset when ready + * + * Note that an initial, extra single reset cycle (assert/release) is + * performed from the generic #riscv_cpu_realize function on machine + * realization. */ - CPUState *cs = CPU(s->devices[OT_DARJEELING_SOC_DEV_HART]); + CPUState *cs = CPU(s->devices[OT_DJ_SOC_DEV_HART]); resettable_assert_reset(OBJECT(cs), RESET_TYPE_COLD); } -static void ot_darjeeling_soc_reset_exit(Object *obj) +static void ot_dj_soc_reset_exit(Object *obj) { - OtDarjeelingSoCClass *c = RISCV_OT_DARJEELING_SOC_GET_CLASS(obj); - OtDarjeelingSoCState *s = RISCV_OT_DARJEELING_SOC(obj); + OtDjSoCClass *c = RISCV_OT_DJ_SOC_GET_CLASS(obj); + OtDjSoCState *s = RISCV_OT_DJ_SOC(obj); if (c->parent_phases.exit) { c->parent_phases.exit(obj); } /* let ROM_CTRLs get out of reset now */ - resettable_release_reset(OBJECT(s->devices[OT_DARJEELING_SOC_DEV_ROM0]), + resettable_release_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_ROM0]), RESET_TYPE_COLD); - resettable_release_reset(OBJECT(s->devices[OT_DARJEELING_SOC_DEV_ROM1]), + resettable_release_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_ROM1]), RESET_TYPE_COLD); } -static void ot_darjeeling_soc_realize(DeviceState *dev, Error **errp) +static void ot_dj_soc_realize(DeviceState *dev, Error **errp) { - OtDarjeelingSoCState *s = RISCV_OT_DARJEELING_SOC(dev); + OtDjSoCState *s = RISCV_OT_DJ_SOC(dev); (void)errp; - CPUState *cpu = CPU(s->devices[OT_DARJEELING_SOC_DEV_HART]); + CPUState *cpu = CPU(s->devices[OT_DJ_SOC_DEV_HART]); cpu->memory = get_system_memory(); cpu->cpu_index = 0; /* Link, define properties and realize devices, then connect GPIOs */ ibex_configure_devices_with_id(s->devices, dev->parent_bus, "ot_id", "", - false, ot_darjeeling_soc_devices, - ARRAY_SIZE(ot_darjeeling_soc_devices)); + false, ot_dj_soc_devices, + ARRAY_SIZE(ot_dj_soc_devices)); Object *oas; @@ -1148,20 +1194,19 @@ static void ot_darjeeling_soc_realize(DeviceState *dev, Error **errp) AddressSpace *ctn_as = ot_address_space_get(OT_ADDRESS_SPACE(oas)); MemoryRegion *dbg_mr = g_new0(MemoryRegion, 1u); - memory_region_init(dbg_mr, OBJECT(dev), "dbg-xbar", - OT_DARJEELING_DBG_XBAR_APERTURE); + memory_region_init(dbg_mr, OBJECT(dev), "dbg-xbar", OT_DJ_DBG_XBAR_SIZE); MemoryRegion *mrs[IBEX_MEMMAP_REGIDX_COUNT] = { - [OT_DARJEELING_DEFAULT_MEMORY_REGION] = cpu->memory, - [OT_DARJEELING_CTN_MEMORY_REGION] = ctn_as->root, - [OT_DARJEELING_DEBUG_MEMORY_REGION] = dbg_mr, + [OT_DJ_DEFAULT_MEMORY_REGION] = cpu->memory, + [OT_DJ_CTN_MEMORY_REGION] = ctn_as->root, + [OT_DJ_DEBUG_MEMORY_REGION] = dbg_mr, }; - ibex_map_devices_mask(s->devices, mrs, ot_darjeeling_soc_devices, - ARRAY_SIZE(ot_darjeeling_soc_devices), + ibex_map_devices_mask(s->devices, mrs, ot_dj_soc_devices, + ARRAY_SIZE(ot_dj_soc_devices), IBEX_MEMMAP_MAKE_REG_MASK( - OT_DARJEELING_DEFAULT_MEMORY_REGION) | + OT_DJ_DEFAULT_MEMORY_REGION) | IBEX_MEMMAP_MAKE_REG_MASK( - OT_DARJEELING_DEBUG_MEMORY_REGION)); + OT_DJ_DEBUG_MEMORY_REGION)); AddressSpace *dbg_as = g_new0(AddressSpace, 1u); address_space_init(dbg_as, dbg_mr, "dbg-as"); @@ -1182,8 +1227,7 @@ static void ot_darjeeling_soc_realize(DeviceState *dev, Error **errp) */ MemoryRegion *ctn_dma_mr = g_new0(MemoryRegion, 1u); memory_region_init(ctn_dma_mr, OBJECT(dev), "ctn-dma", - OT_DARJEELING_CTN_REGION_OFFSET + - OT_DARJEELING_CTN_REGION_SIZE); + OT_DJ_CTN_REGION_OFFSET + OT_DJ_CTN_REGION_SIZE); /* create an AS view for this new root region */ AddressSpace *ctn_dma_as = g_new0(AddressSpace, 1u); @@ -1192,10 +1236,8 @@ static void ot_darjeeling_soc_realize(DeviceState *dev, Error **errp) /* create and map an alias to the CTN MR into the elevated region */ MemoryRegion *ctn_amr = g_new0(MemoryRegion, 1u); memory_region_init_alias(ctn_amr, OBJECT(dev), "ctn-dma-alias", - ctn_as->root, 0u, - (uint64_t)OT_DARJEELING_CTN_REGION_SIZE); - memory_region_add_subregion(ctn_dma_mr, - (hwaddr)OT_DARJEELING_CTN_REGION_OFFSET, + ctn_as->root, 0u, (uint64_t)OT_DJ_CTN_REGION_SIZE); + memory_region_add_subregion(ctn_dma_mr, (hwaddr)OT_DJ_CTN_REGION_OFFSET, ctn_amr); oas = object_new(TYPE_OT_ADDRESS_SPACE); @@ -1206,62 +1248,61 @@ static void ot_darjeeling_soc_realize(DeviceState *dev, Error **errp) ibex_load_kernel(cpu->as); } -static void ot_darjeeling_soc_init(Object *obj) +static void ot_dj_soc_init(Object *obj) { - OtDarjeelingSoCState *s = RISCV_OT_DARJEELING_SOC(obj); + OtDjSoCState *s = RISCV_OT_DJ_SOC(obj); jtag_configure_tap(IBEX_TAP_IR_LENGTH, DARJEELING_TAP_IDCODE); - s->devices = - ibex_create_devices(ot_darjeeling_soc_devices, - ARRAY_SIZE(ot_darjeeling_soc_devices), DEVICE(s)); + s->devices = ibex_create_devices(ot_dj_soc_devices, + ARRAY_SIZE(ot_dj_soc_devices), DEVICE(s)); } -static void ot_darjeeling_soc_class_init(ObjectClass *oc, void *data) +static void ot_dj_soc_class_init(ObjectClass *oc, void *data) { - OtDarjeelingSoCClass *sc = RISCV_OT_DARJEELING_SOC_CLASS(oc); + OtDjSoCClass *sc = RISCV_OT_DJ_SOC_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); ResettableClass *rc = RESETTABLE_CLASS(dc); (void)data; - resettable_class_set_parent_phases(rc, NULL, &ot_darjeeling_soc_reset_hold, - &ot_darjeeling_soc_reset_exit, + resettable_class_set_parent_phases(rc, NULL, &ot_dj_soc_reset_hold, + &ot_dj_soc_reset_exit, &sc->parent_phases); - dc->realize = &ot_darjeeling_soc_realize; + dc->realize = &ot_dj_soc_realize; dc->user_creatable = false; } -static const TypeInfo ot_darjeeling_soc_type_info = { - .name = TYPE_RISCV_OT_DARJEELING_SOC, +static const TypeInfo ot_dj_soc_type_info = { + .name = TYPE_RISCV_OT_DJ_SOC, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(OtDarjeelingSoCState), - .instance_init = &ot_darjeeling_soc_init, - .class_init = &ot_darjeeling_soc_class_init, - .class_size = sizeof(OtDarjeelingSoCClass), + .instance_size = sizeof(OtDjSoCState), + .instance_init = &ot_dj_soc_init, + .class_init = &ot_dj_soc_class_init, + .class_size = sizeof(OtDjSoCClass), }; -static void ot_darjeeling_soc_register_types(void) +static void ot_dj_soc_register_types(void) { - type_register_static(&ot_darjeeling_soc_type_info); + type_register_static(&ot_dj_soc_type_info); } -type_init(ot_darjeeling_soc_register_types); +type_init(ot_dj_soc_register_types); /* ------------------------------------------------------------------------ */ /* Board */ /* ------------------------------------------------------------------------ */ -static void ot_darjeeling_board_realize(DeviceState *dev, Error **errp) +static void ot_dj_board_realize(DeviceState *dev, Error **errp) { - OtDarjeelingBoardState *board = RISCV_OT_DARJEELING_BOARD(dev); + OtDjBoardState *board = RISCV_OT_DJ_BOARD(dev); - DeviceState *soc = board->devices[OT_DARJEELING_BOARD_DEV_SOC]; + DeviceState *soc = board->devices[OT_DJ_BOARD_DEV_SOC]; object_property_add_child(OBJECT(board), "soc", OBJECT(soc)); /* CTN memory region */ MemoryRegion *ctn_mr = g_new0(MemoryRegion, 1u); memory_region_init(ctn_mr, OBJECT(dev), "ctn-xbar", - (uint64_t)OT_DARJEELING_CTN_REGION_SIZE); + (uint64_t)OT_DJ_CTN_REGION_SIZE); /* CTN address space */ AddressSpace *ctn_as = g_new0(AddressSpace, 1); @@ -1270,7 +1311,7 @@ static void ot_darjeeling_board_realize(DeviceState *dev, Error **errp) object_property_add_child(OBJECT(dev), ctn_as->name, oas); ot_address_space_set(OT_ADDRESS_SPACE(oas), ctn_as); - OtDarjeelingSoCState *s = RISCV_OT_DARJEELING_SOC(soc); + OtDjSoCState *s = RISCV_OT_DJ_SOC(soc); BusState *bus = sysbus_get_default(); qdev_realize_and_unref(DEVICE(soc), bus, &error_fatal); @@ -1278,19 +1319,18 @@ static void ot_darjeeling_board_realize(DeviceState *dev, Error **errp) /* CTN RAM */ MemoryRegion *ctn_ram = g_new0(MemoryRegion, 1u); memory_region_init_ram_nomigrate(ctn_ram, OBJECT(s), "ctn-ram", - OT_DARJEELING_CTN_RAM_SIZE, errp); - memory_region_add_subregion(ctn_mr, OT_DARJEELING_CTN_RAM_ADDR, ctn_ram); + OT_DJ_CTN_RAM_SIZE, errp); + memory_region_add_subregion(ctn_mr, OT_DJ_CTN_RAM_ADDR, ctn_ram); /* CTN aliased memory in CPU address space */ MemoryRegion *ctn_alias_mr = g_new0(MemoryRegion, 1u); memory_region_init_alias(ctn_alias_mr, OBJECT(dev), "ctn-alias", ctn_mr, 0u, - (uint64_t)OT_DARJEELING_CTN_REGION_SIZE); + (uint64_t)OT_DJ_CTN_REGION_SIZE); memory_region_add_subregion(get_system_memory(), - (hwaddr)OT_DARJEELING_CTN_REGION_OFFSET, - ctn_alias_mr); + (hwaddr)OT_DJ_CTN_REGION_OFFSET, ctn_alias_mr); - DeviceState *spihost = s->devices[OT_DARJEELING_SOC_DEV_SPI_HOST0]; - DeviceState *flash = board->devices[OT_DARJEELING_BOARD_DEV_FLASH]; + DeviceState *spihost = s->devices[OT_DJ_SOC_DEV_SPI_HOST0]; + DeviceState *flash = board->devices[OT_DJ_BOARD_DEV_FLASH]; BusState *spibus = qdev_get_child_bus(spihost, "spi0"); g_assert(spibus); @@ -1305,108 +1345,132 @@ static void ot_darjeeling_board_realize(DeviceState *dev, Error **errp) qemu_irq cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0); qdev_connect_gpio_out_named(spihost, SSI_GPIO_CS, 0, cs); - DeviceState *devproxy = board->devices[OT_DARJEELING_BOARD_DEV_DEV_PROXY]; + DeviceState *devproxy = board->devices[OT_DJ_BOARD_DEV_DEV_PROXY]; object_property_add_child(OBJECT(board), "devproxy", OBJECT(devproxy)); qdev_realize_and_unref(devproxy, NULL, errp); } -static void ot_darjeeling_board_init(Object *obj) +static void ot_dj_board_init(Object *obj) { - OtDarjeelingBoardState *s = RISCV_OT_DARJEELING_BOARD(obj); + OtDjBoardState *s = RISCV_OT_DJ_BOARD(obj); - s->devices = g_new0(DeviceState *, _OT_DARJEELING_BOARD_DEV_COUNT); - s->devices[OT_DARJEELING_BOARD_DEV_SOC] = - qdev_new(TYPE_RISCV_OT_DARJEELING_SOC); - s->devices[OT_DARJEELING_BOARD_DEV_FLASH] = qdev_new("is25wp128"); - s->devices[OT_DARJEELING_BOARD_DEV_DEV_PROXY] = qdev_new(TYPE_OT_DEV_PROXY); + s->devices = g_new0(DeviceState *, OT_DJ_BOARD_DEV_COUNT); + s->devices[OT_DJ_BOARD_DEV_SOC] = qdev_new(TYPE_RISCV_OT_DJ_SOC); + s->devices[OT_DJ_BOARD_DEV_FLASH] = qdev_new("is25wp128"); + s->devices[OT_DJ_BOARD_DEV_DEV_PROXY] = qdev_new(TYPE_OT_DEV_PROXY); } -static void ot_darjeeling_board_class_init(ObjectClass *oc, void *data) +static void ot_dj_board_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); (void)data; - dc->realize = &ot_darjeeling_board_realize; + dc->realize = &ot_dj_board_realize; } -static const TypeInfo ot_darjeeling_board_type_info = { - .name = TYPE_RISCV_OT_DARJEELING_BOARD, +static const TypeInfo ot_dj_board_type_info = { + .name = TYPE_RISCV_OT_DJ_BOARD, .parent = TYPE_DEVICE, - .instance_size = sizeof(OtDarjeelingBoardState), - .instance_init = &ot_darjeeling_board_init, - .class_init = &ot_darjeeling_board_class_init, + .instance_size = sizeof(OtDjBoardState), + .instance_init = &ot_dj_board_init, + .class_init = &ot_dj_board_class_init, }; -static void ot_darjeeling_board_register_types(void) +static void ot_dj_board_register_types(void) { - type_register_static(&ot_darjeeling_board_type_info); + type_register_static(&ot_dj_board_type_info); } -type_init(ot_darjeeling_board_register_types); +type_init(ot_dj_board_register_types); /* ------------------------------------------------------------------------ */ /* Machine */ /* ------------------------------------------------------------------------ */ -static bool ot_darjeeling_machine_get_no_epmp_cfg(Object *obj, Error **errp) +static bool ot_dj_machine_get_no_epmp_cfg(Object *obj, Error **errp) { - OtDarjeelingMachineState *s = RISCV_OT_DARJEELING_MACHINE(obj); + OtDjMachineState *s = RISCV_OT_DJ_MACHINE(obj); (void)errp; return s->no_epmp_cfg; } -static void -ot_darjeeling_machine_set_no_epmp_cfg(Object *obj, bool value, Error **errp) +static void ot_dj_machine_set_no_epmp_cfg(Object *obj, bool value, Error **errp) { - OtDarjeelingMachineState *s = RISCV_OT_DARJEELING_MACHINE(obj); + OtDjMachineState *s = RISCV_OT_DJ_MACHINE(obj); (void)errp; s->no_epmp_cfg = value; } -static void ot_darjeeling_machine_instance_init(Object *obj) +static void ot_dj_machine_transitional_reset(Object *obj) +{ + (void)obj; + + qemu_devices_reset(SHUTDOWN_CAUSE_GUEST_RESET); +} + +static ResettableTrFunction ot_dj_get_transitional_reset(Object *obj) { - OtDarjeelingMachineState *s = RISCV_OT_DARJEELING_MACHINE(obj); + (void)obj; + + return ot_dj_machine_transitional_reset; +} + +static ResettableState *ot_dj_get_reset_state(Object *obj) +{ + OtDjMachineState *s = RISCV_OT_DJ_MACHINE(obj); + + return &s->reset; +} + +static void ot_dj_machine_instance_init(Object *obj) +{ + OtDjMachineState *s = RISCV_OT_DJ_MACHINE(obj); s->no_epmp_cfg = false; - object_property_add_bool(obj, "no-epmp-cfg", - &ot_darjeeling_machine_get_no_epmp_cfg, - &ot_darjeeling_machine_set_no_epmp_cfg); + object_property_add_bool(obj, "no-epmp-cfg", &ot_dj_machine_get_no_epmp_cfg, + &ot_dj_machine_set_no_epmp_cfg); object_property_set_description(obj, "no-epmp-cfg", "Skip default ePMP configuration"); } -static void ot_darjeeling_machine_init(MachineState *state) +static void ot_dj_machine_init(MachineState *state) { - DeviceState *dev = qdev_new(TYPE_RISCV_OT_DARJEELING_BOARD); + DeviceState *dev = qdev_new(TYPE_RISCV_OT_DJ_BOARD); object_property_add_child(OBJECT(state), "board", OBJECT(dev)); qdev_realize(dev, NULL, &error_fatal); } -static void ot_darjeeling_machine_class_init(ObjectClass *oc, void *data) +static void ot_dj_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); (void)data; mc->desc = "RISC-V Board compatible with OpenTitan Darjeeling platform"; - mc->init = ot_darjeeling_machine_init; + mc->init = ot_dj_machine_init; mc->max_cpus = 1u; mc->default_cpus = 1u; + + ResettableClass *rc = RESETTABLE_CLASS(oc); + + rc->get_state = &ot_dj_get_reset_state; + rc->get_transitional_function = &ot_dj_get_transitional_reset; } -static const TypeInfo ot_darjeeling_machine_type_info = { - .name = TYPE_RISCV_OT_DARJEELING_MACHINE, +static const TypeInfo ot_dj_machine_type_info = { + .name = TYPE_RISCV_OT_DJ_MACHINE, .parent = TYPE_MACHINE, - .instance_size = sizeof(OtDarjeelingMachineState), - .instance_init = &ot_darjeeling_machine_instance_init, - .class_init = &ot_darjeeling_machine_class_init, + .instance_size = sizeof(OtDjMachineState), + .instance_init = &ot_dj_machine_instance_init, + .class_init = &ot_dj_machine_class_init, + .interfaces = (InterfaceInfo[]){ { TYPE_RESETTABLE_INTERFACE }, {} }, }; -static void ot_darjeeling_machine_register_types(void) +static void ot_dj_machine_register_types(void) { - type_register_static(&ot_darjeeling_machine_type_info); + type_register_static(&ot_dj_machine_type_info); } -type_init(ot_darjeeling_machine_register_types); +type_init(ot_dj_machine_register_types); diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index bb9c560e6630..60889a7b5120 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -70,74 +70,81 @@ /* Forward Declarations */ /* ------------------------------------------------------------------------ */ -static void ot_earlgrey_soc_flash_ctrl_configure( +static void ot_eg_soc_flash_ctrl_configure( DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); -static void ot_earlgrey_soc_hart_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); -static void ot_earlgrey_soc_otp_ctrl_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); -static void ot_earlgrey_soc_uart_configure( +static void ot_eg_soc_hart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent); +static void ot_eg_soc_otp_ctrl_configure( DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); +static void ot_eg_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent); /* ------------------------------------------------------------------------ */ /* Constants */ /* ------------------------------------------------------------------------ */ -enum OtEarlGreySocDevice { - OT_EARLGREY_SOC_DEV_ADC_CTRL, - OT_EARLGREY_SOC_DEV_AES, - OT_EARLGREY_SOC_DEV_ALERT_HANDLER, - OT_EARLGREY_SOC_DEV_AON_TIMER, - OT_EARLGREY_SOC_DEV_AST, - OT_EARLGREY_SOC_DEV_CLKMGR, - OT_EARLGREY_SOC_DEV_CSRNG, - OT_EARLGREY_SOC_DEV_EDN0, - OT_EARLGREY_SOC_DEV_EDN1, - OT_EARLGREY_SOC_DEV_ENTROPY_SRC, - OT_EARLGREY_SOC_DEV_FLASH_CTRL, - OT_EARLGREY_SOC_DEV_GPIO, - OT_EARLGREY_SOC_DEV_HART, - OT_EARLGREY_SOC_DEV_HMAC, - OT_EARLGREY_SOC_DEV_I2C0, - OT_EARLGREY_SOC_DEV_I2C1, - OT_EARLGREY_SOC_DEV_I2C2, - OT_EARLGREY_SOC_DEV_IBEX_WRAPPER, - OT_EARLGREY_SOC_DEV_KEYMGR, - OT_EARLGREY_SOC_DEV_KMAC, - OT_EARLGREY_SOC_DEV_LC_CTRL, - OT_EARLGREY_SOC_DEV_OTBN, - OT_EARLGREY_SOC_DEV_OTP_CTRL, - OT_EARLGREY_SOC_DEV_PATTGEN, - OT_EARLGREY_SOC_DEV_PINMUX, - OT_EARLGREY_SOC_DEV_PLIC, - OT_EARLGREY_SOC_DEV_PWM, - OT_EARLGREY_SOC_DEV_PWRMGR, - OT_EARLGREY_SOC_DEV_SRAM_RET_CTRL, - OT_EARLGREY_SOC_DEV_ROM_CTRL, - OT_EARLGREY_SOC_DEV_RSTMGR, - OT_EARLGREY_SOC_DEV_RV_DM, - OT_EARLGREY_SOC_DEV_RV_DM_MEM, - OT_EARLGREY_SOC_DEV_SENSOR_CTRL, - OT_EARLGREY_SOC_DEV_SPI_DEVICE, - OT_EARLGREY_SOC_DEV_SPI_HOST0, - OT_EARLGREY_SOC_DEV_SPI_HOST1, - OT_EARLGREY_SOC_DEV_SRAM_MAIN_CTRL, - OT_EARLGREY_SOC_DEV_SYSRST_CTRL, - OT_EARLGREY_SOC_DEV_TIMER, - OT_EARLGREY_SOC_DEV_UART0, - OT_EARLGREY_SOC_DEV_UART1, - OT_EARLGREY_SOC_DEV_UART2, - OT_EARLGREY_SOC_DEV_UART3, - OT_EARLGREY_SOC_DEV_USBDEV, +enum OtEGSocDevice { + OT_EG_SOC_DEV_ADC_CTRL, + OT_EG_SOC_DEV_AES, + OT_EG_SOC_DEV_ALERT_HANDLER, + OT_EG_SOC_DEV_AON_TIMER, + OT_EG_SOC_DEV_AST, + OT_EG_SOC_DEV_CLKMGR, + OT_EG_SOC_DEV_CSRNG, + OT_EG_SOC_DEV_EDN0, + OT_EG_SOC_DEV_EDN1, + OT_EG_SOC_DEV_ENTROPY_SRC, + OT_EG_SOC_DEV_FLASH_CTRL, + OT_EG_SOC_DEV_GPIO, + OT_EG_SOC_DEV_HART, + OT_EG_SOC_DEV_HMAC, + OT_EG_SOC_DEV_I2C0, + OT_EG_SOC_DEV_I2C1, + OT_EG_SOC_DEV_I2C2, + OT_EG_SOC_DEV_IBEX_WRAPPER, + OT_EG_SOC_DEV_KEYMGR, + OT_EG_SOC_DEV_KMAC, + OT_EG_SOC_DEV_LC_CTRL, + OT_EG_SOC_DEV_OTBN, + OT_EG_SOC_DEV_OTP_CTRL, + OT_EG_SOC_DEV_PATTGEN, + OT_EG_SOC_DEV_PINMUX, + OT_EG_SOC_DEV_PLIC, + OT_EG_SOC_DEV_PWM, + OT_EG_SOC_DEV_PWRMGR, + OT_EG_SOC_DEV_SRAM_RET_CTRL, + OT_EG_SOC_DEV_ROM_CTRL, + OT_EG_SOC_DEV_RSTMGR, + OT_EG_SOC_DEV_RV_DM, + OT_EG_SOC_DEV_RV_DM_MEM, + 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_TIMER, + OT_EG_SOC_DEV_UART0, + OT_EG_SOC_DEV_UART1, + OT_EG_SOC_DEV_UART2, + OT_EG_SOC_DEV_UART3, + OT_EG_SOC_DEV_USBDEV, +}; + +enum OtEgResetRequest { + OT_EG_RESET_SYSRST_CTRL, + OT_EG_RESET_AON_TIMER, + OT_EG_RESET_SENSOR_CTRL, + OT_EG_RESET_COUNT }; /* EarlGrey/CW310 Peripheral clock is 2.5 MHz */ -#define OT_EARLGREY_PERIPHERAL_CLK_HZ 2500000u +#define OT_EG_PERIPHERAL_CLK_HZ 2500000u /* EarlGrey/CW310 AON clock is 250 kHz */ -#define OT_EARLGREY_AON_CLK_HZ 250000u +#define OT_EG_AON_CLK_HZ 250000u -static const uint8_t ot_earlgrey_pmp_cfgs[] = { +static const uint8_t ot_eg_pmp_cfgs[] = { /* clang-format off */ IBEX_PMP_CFG(0, IBEX_PMP_MODE_OFF, 0, 0, 0), IBEX_PMP_CFG(0, IBEX_PMP_MODE_OFF, 0, 0, 0), @@ -158,7 +165,7 @@ static const uint8_t ot_earlgrey_pmp_cfgs[] = { /* clang-format on */ }; -static const uint32_t ot_earlgrey_pmp_addrs[] = { +static const uint32_t ot_eg_pmp_addrs[] = { /* clang-format off */ IBEX_PMP_ADDR(0x00000000), IBEX_PMP_ADDR(0x00000000), @@ -179,18 +186,18 @@ static const uint32_t ot_earlgrey_pmp_addrs[] = { /* clang-format on */ }; -#define OT_EARLGREY_MSECCFG IBEX_MSECCFG(1, 1, 0) +#define OT_EG_MSECCFG IBEX_MSECCFG(1, 1, 0) -#define OT_EARLGREY_SOC_GPIO(_irq_, _target_, _num_) \ - IBEX_GPIO(_irq_, OT_EARLGREY_SOC_DEV_##_target_, _num_) +#define OT_EG_SOC_GPIO(_irq_, _target_, _num_) \ + IBEX_GPIO(_irq_, OT_EG_SOC_DEV_##_target_, _num_) -#define OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(_irq_, _target_, _num_) \ - IBEX_GPIO_SYSBUS_IRQ(_irq_, OT_EARLGREY_SOC_DEV_##_target_, _num_) +#define OT_EG_SOC_GPIO_SYSBUS_IRQ(_irq_, _target_, _num_) \ + IBEX_GPIO_SYSBUS_IRQ(_irq_, OT_EG_SOC_DEV_##_target_, _num_) -#define OT_EARLGREY_SOC_DEVLINK(_pname_, _target_) \ - IBEX_DEVLINK(_pname_, OT_EARLGREY_SOC_DEV_##_target_) +#define OT_EG_SOC_DEVLINK(_pname_, _target_) \ + IBEX_DEVLINK(_pname_, OT_EG_SOC_DEV_##_target_) -#define OT_EARLGREY_SOC_SIGNAL(_sname_, _snum_, _tgt_, _tname_, _tnum_) \ +#define OT_EG_SOC_SIGNAL(_sname_, _snum_, _tgt_, _tname_, _tnum_) \ { \ .out = { \ .name = (_sname_), \ @@ -198,13 +205,22 @@ static const uint32_t ot_earlgrey_pmp_addrs[] = { }, \ .in = { \ .name = (_tname_), \ - .index = (OT_EARLGREY_SOC_DEV_ ## _tgt_), \ + .index = (OT_EG_SOC_DEV_ ## _tgt_), \ .num = (_tnum_), \ } \ } -#define OT_EARLGREY_SOC_CLKMGR_HINT(_num_) \ - OT_EARLGREY_SOC_SIGNAL(OT_CLOCK_ACTIVE, 0, CLKMGR, OT_CLKMGR_HINT, _num_) +/* Request link */ +#define OT_EG_SOC_REQ(_req_, _tgt_) \ + OT_EG_SOC_SIGNAL(_req_##_REQ, 0, _tgt_, _req_##_REQ, 0) + +/* Response link */ +#define OT_EG_SOC_RSP(_rsp_, _tgt_) \ + OT_EG_SOC_SIGNAL(_rsp_##_RSP, 0, _tgt_, _rsp_##_RSP, 0) + + +#define OT_EG_SOC_CLKMGR_HINT(_num_) \ + OT_EG_SOC_SIGNAL(OT_CLOCK_ACTIVE, 0, CLKMGR, OT_CLKMGR_HINT, _num_) /* * MMIO/interrupt mapping as per: @@ -212,11 +228,11 @@ static const uint32_t ot_earlgrey_pmp_addrs[] = { * and * lowRISC/opentitan: hw/top_earlgrey/sw/autogen/top_earlgrey.h */ -static const IbexDeviceDef ot_earlgrey_soc_devices[] = { +static const IbexDeviceDef ot_eg_soc_devices[] = { /* clang-format off */ - [OT_EARLGREY_SOC_DEV_HART] = { + [OT_EG_SOC_DEV_HART] = { .type = TYPE_RISCV_CPU_LOWRISC_IBEX, - .cfg = &ot_earlgrey_soc_hart_configure, + .cfg = &ot_eg_soc_hart_configure, .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_BOOL_PROP("m", true), IBEX_DEV_BOOL_PROP("pmp", true), @@ -230,7 +246,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { IBEX_DEV_BOOL_PROP("start-powered-off", true) ), }, - [OT_EARLGREY_SOC_DEV_RV_DM_MEM] = { + [OT_EG_SOC_DEV_RV_DM_MEM] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-rv_dm_mem", .cfg = &ibex_unimp_configure, @@ -238,155 +254,155 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x00010000u, 0x1000u } ), }, - [OT_EARLGREY_SOC_DEV_UART0] = { + [OT_EG_SOC_DEV_UART0] = { .type = TYPE_OT_UART, - .cfg = &ot_earlgrey_soc_uart_configure, + .cfg = &ot_eg_soc_uart_configure, .instance = 0, .memmap = MEMMAPENTRIES( { 0x40000000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 1), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 2), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 3), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 4), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 5), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 6), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 7), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 8) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 1), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 2), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 3), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 4), + OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 5), + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 6), + OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 7), + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 8) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_EARLGREY_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) ), }, - [OT_EARLGREY_SOC_DEV_UART1] = { + [OT_EG_SOC_DEV_UART1] = { .type = TYPE_OT_UART, - .cfg = &ot_earlgrey_soc_uart_configure, + .cfg = &ot_eg_soc_uart_configure, .instance = 1, .memmap = MEMMAPENTRIES( { 0x40010000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 9), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 10), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 11), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 12), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 13), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 14), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 15), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 16) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 9), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 10), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 11), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 12), + OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 13), + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 14), + OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 15), + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 16) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_EARLGREY_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) ), }, - [OT_EARLGREY_SOC_DEV_UART2] = { + [OT_EG_SOC_DEV_UART2] = { .type = TYPE_OT_UART, - .cfg = &ot_earlgrey_soc_uart_configure, + .cfg = &ot_eg_soc_uart_configure, .instance = 2, .memmap = MEMMAPENTRIES( { 0x40020000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 17), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 18), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 19), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 20), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 21), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 22), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 23), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 24) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 17), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 18), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 19), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 20), + OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 21), + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 22), + OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 23), + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 24) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_EARLGREY_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) ), }, - [OT_EARLGREY_SOC_DEV_UART3] = { + [OT_EG_SOC_DEV_UART3] = { .type = TYPE_OT_UART, - .cfg = &ot_earlgrey_soc_uart_configure, + .cfg = &ot_eg_soc_uart_configure, .instance = 3, .memmap = MEMMAPENTRIES( { 0x40030000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 25), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 26), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 27), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 28), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 29), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 30), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 31), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 32) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 25), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 26), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 27), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 28), + OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 29), + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 30), + OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 31), + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 32) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_EARLGREY_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) ), }, - [OT_EARLGREY_SOC_DEV_GPIO] = { + [OT_EG_SOC_DEV_GPIO] = { .type = TYPE_OT_GPIO, .name = "ot-gpio", .memmap = MEMMAPENTRIES( { 0x40040000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 33), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 34), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 35), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 36), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 37), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 38), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 49), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 40), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 41), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 42), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 43), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 44), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(12, PLIC, 45), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(13, PLIC, 46), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(14, PLIC, 47), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(15, PLIC, 48), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(16, PLIC, 59), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(17, PLIC, 50), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(18, PLIC, 51), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(19, PLIC, 52), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(20, PLIC, 53), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(21, PLIC, 54), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(22, PLIC, 55), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(23, PLIC, 56), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(24, PLIC, 57), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(25, PLIC, 58), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(26, PLIC, 69), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(27, PLIC, 60), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 61), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 62), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 63), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 64) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 33), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 34), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 35), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 36), + OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 37), + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 38), + OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 49), + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 40), + OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 41), + OT_EG_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 42), + OT_EG_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 43), + OT_EG_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 44), + OT_EG_SOC_GPIO_SYSBUS_IRQ(12, PLIC, 45), + OT_EG_SOC_GPIO_SYSBUS_IRQ(13, PLIC, 46), + OT_EG_SOC_GPIO_SYSBUS_IRQ(14, PLIC, 47), + OT_EG_SOC_GPIO_SYSBUS_IRQ(15, PLIC, 48), + OT_EG_SOC_GPIO_SYSBUS_IRQ(16, PLIC, 59), + OT_EG_SOC_GPIO_SYSBUS_IRQ(17, PLIC, 50), + OT_EG_SOC_GPIO_SYSBUS_IRQ(18, PLIC, 51), + OT_EG_SOC_GPIO_SYSBUS_IRQ(19, PLIC, 52), + OT_EG_SOC_GPIO_SYSBUS_IRQ(20, PLIC, 53), + OT_EG_SOC_GPIO_SYSBUS_IRQ(21, PLIC, 54), + OT_EG_SOC_GPIO_SYSBUS_IRQ(22, PLIC, 55), + OT_EG_SOC_GPIO_SYSBUS_IRQ(23, PLIC, 56), + OT_EG_SOC_GPIO_SYSBUS_IRQ(24, PLIC, 57), + OT_EG_SOC_GPIO_SYSBUS_IRQ(25, PLIC, 58), + OT_EG_SOC_GPIO_SYSBUS_IRQ(26, PLIC, 69), + OT_EG_SOC_GPIO_SYSBUS_IRQ(27, PLIC, 60), + OT_EG_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 61), + OT_EG_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 62), + OT_EG_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 63), + OT_EG_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 64) ) }, - [OT_EARLGREY_SOC_DEV_SPI_DEVICE] = { + [OT_EG_SOC_DEV_SPI_DEVICE] = { .type = TYPE_OT_SPI_DEVICE, .memmap = MEMMAPENTRIES( { 0x40050000u, 0x2000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 65), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 66), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 67), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 68), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 69), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 70), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 71), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 72), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 73), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 74), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 75), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 76) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 65), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 66), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 67), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 68), + OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 69), + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 70), + OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 71), + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 72), + OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 73), + OT_EG_SOC_GPIO_SYSBUS_IRQ(9, PLIC, 74), + OT_EG_SOC_GPIO_SYSBUS_IRQ(10, PLIC, 75), + OT_EG_SOC_GPIO_SYSBUS_IRQ(11, PLIC, 76) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_BOOL_PROP("dpsram", true) ), }, - [OT_EARLGREY_SOC_DEV_I2C0] = { + [OT_EG_SOC_DEV_I2C0] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, @@ -395,7 +411,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40080000u, 0x80u } ), }, - [OT_EARLGREY_SOC_DEV_I2C1] = { + [OT_EG_SOC_DEV_I2C1] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, @@ -404,7 +420,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40090000u, 0x80u } ), }, - [OT_EARLGREY_SOC_DEV_I2C2] = { + [OT_EG_SOC_DEV_I2C2] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, @@ -413,7 +429,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x400a0000u, 0x80u } ), }, - [OT_EARLGREY_SOC_DEV_PATTGEN] = { + [OT_EG_SOC_DEV_PATTGEN] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-pattgen", .cfg = &ibex_unimp_configure, @@ -421,45 +437,48 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x400e0000u, 0x40u } ), }, - [OT_EARLGREY_SOC_DEV_TIMER] = { + [OT_EG_SOC_DEV_TIMER] = { .type = TYPE_OT_TIMER, .memmap = MEMMAPENTRIES( { 0x40100000u, 0x200u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO(0, HART, IRQ_M_TIMER), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 124) + OT_EG_SOC_GPIO(0, HART, IRQ_M_TIMER), + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 124) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_EARLGREY_PERIPHERAL_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) ), }, - [OT_EARLGREY_SOC_DEV_OTP_CTRL] = { + [OT_EG_SOC_DEV_OTP_CTRL] = { .type = TYPE_OT_OTP_EG, - .cfg = &ot_earlgrey_soc_otp_ctrl_configure, + .cfg = &ot_eg_soc_otp_ctrl_configure, .memmap = MEMMAPENTRIES( { 0x40130000u, 0x2000u }, { 0x40132000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 125), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 126) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 125), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 126) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("edn", EDN0) + OT_EG_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 1u) ), }, - [OT_EARLGREY_SOC_DEV_LC_CTRL] = { + [OT_EG_SOC_DEV_LC_CTRL] = { .type = TYPE_OT_LC_CTRL, .memmap = MEMMAPENTRIES( { 0x40140000u, 0x100u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_RSP(OT_PWRMGR_LC, PWRMGR) + ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("otp_ctrl", OTP_CTRL), - OT_EARLGREY_SOC_DEVLINK("kmac", KMAC) + OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_EG_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 4u) @@ -472,53 +491,53 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { IBEX_DEV_UINT_PROP("kmac-app", 1u) ) }, - [OT_EARLGREY_SOC_DEV_ALERT_HANDLER] = { + [OT_EG_SOC_DEV_ALERT_HANDLER] = { .type = TYPE_OT_ALERT_EG, .memmap = MEMMAPENTRIES( { 0x40150000u, 0x800u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 127), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 128), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 129), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 130) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 127), + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 128), + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 129), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 130) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("edn", EDN0) + OT_EG_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 4u) ), }, - [OT_EARLGREY_SOC_DEV_SPI_HOST0] = { + [OT_EG_SOC_DEV_SPI_HOST0] = { .type = TYPE_OT_SPI_HOST, .instance = 0, .memmap = MEMMAPENTRIES( { 0x40300000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 131), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 132) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 131), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 132) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("bus-num", 0) ), }, - [OT_EARLGREY_SOC_DEV_SPI_HOST1] = { + [OT_EG_SOC_DEV_SPI_HOST1] = { .type = TYPE_OT_SPI_HOST, .instance = 1, .memmap = MEMMAPENTRIES( { 0x40310000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 133), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 134) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 133), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 134) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("bus-num", 1) ), }, - [OT_EARLGREY_SOC_DEV_USBDEV] = { + [OT_EG_SOC_DEV_USBDEV] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-usbdev", .cfg = &ibex_unimp_configure, @@ -526,47 +545,46 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40320000u, 0x1000u } ), }, - [OT_EARLGREY_SOC_DEV_PWRMGR] = { + [OT_EG_SOC_DEV_PWRMGR] = { .type = TYPE_OT_PWRMGR, .memmap = MEMMAPENTRIES( { 0x40400000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 152), + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 152), /* loopback signal since Earlgrey OTP signal are not supported yet*/ - OT_EARLGREY_SOC_SIGNAL(OT_PWRMGR_OTP_REQ, 0, PWRMGR, + OT_EG_SOC_SIGNAL(OT_PWRMGR_OTP_REQ, 0, PWRMGR, OT_PWRMGR_OTP_RSP, 0), - /* loopback signal since Earlgrey OTP signal are not supported yet*/ - OT_EARLGREY_SOC_SIGNAL(OT_PWRMGR_LC_REQ, 0, PWRMGR, - OT_PWRMGR_LC_RSP, 0), - OT_EARLGREY_SOC_SIGNAL(OT_PWRMGR_CPU_EN, 0, IBEX_WRAPPER, + OT_EG_SOC_REQ(OT_PWRMGR_LC, LC_CTRL), + OT_EG_SOC_SIGNAL(OT_PWRMGR_CPU_EN, 0, IBEX_WRAPPER, OT_IBEX_WRAPPER_CPU_EN, OT_IBEX_PWRMGR_CPU_EN) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("num-rom", 1u) + IBEX_DEV_UINT_PROP("num-rom", 1u), + IBEX_DEV_UINT_PROP("version", OT_PWMGR_VERSION_EG) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("rstmgr", RSTMGR) + OT_EG_SOC_DEVLINK("rstmgr", RSTMGR) ), }, - [OT_EARLGREY_SOC_DEV_RSTMGR] = { + [OT_EG_SOC_DEV_RSTMGR] = { .type = TYPE_OT_RSTMGR, .memmap = MEMMAPENTRIES( { 0x40410000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_SIGNAL(OT_RSTMGR_SW_RST, 0, PWRMGR, \ + OT_EG_SOC_SIGNAL(OT_RSTMGR_SW_RST, 0, PWRMGR, \ OT_PWRMGR_SW_RST, 0) ), }, - [OT_EARLGREY_SOC_DEV_CLKMGR] = { + [OT_EG_SOC_DEV_CLKMGR] = { .type = TYPE_OT_CLKMGR, .memmap = MEMMAPENTRIES( { 0x40420000u, 0x80u } ), }, - [OT_EARLGREY_SOC_DEV_SYSRST_CTRL] = { + [OT_EG_SOC_DEV_SYSRST_CTRL] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-sysrst_ctrl", .cfg = &ibex_unimp_configure, @@ -574,7 +592,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40430000u, 0x100u } ), }, - [OT_EARLGREY_SOC_DEV_ADC_CTRL] = { + [OT_EG_SOC_DEV_ADC_CTRL] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-adc_ctrl", .cfg = &ibex_unimp_configure, @@ -582,7 +600,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40440000u, 0x80u } ), }, - [OT_EARLGREY_SOC_DEV_PWM] = { + [OT_EG_SOC_DEV_PWM] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-pwm", .cfg = &ibex_unimp_configure, @@ -590,44 +608,42 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40450000u, 0x80u } ), }, - [OT_EARLGREY_SOC_DEV_PINMUX] = { + [OT_EG_SOC_DEV_PINMUX] = { .type = TYPE_OT_PINMUX, .memmap = MEMMAPENTRIES( { 0x40460000u, 0x1000u } ), }, - [OT_EARLGREY_SOC_DEV_AON_TIMER] = { + [OT_EG_SOC_DEV_AON_TIMER] = { .type = TYPE_OT_AON_TIMER, .memmap = MEMMAPENTRIES( { 0x40470000u, 0x40u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 155), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 156), - OT_EARLGREY_SOC_SIGNAL(OT_AON_TIMER_WKUP, 0, PWRMGR, \ - OT_PWRMGR_WKUP, \ - OT_PWRMGR_WAKEUP_AON_TIMER), - OT_EARLGREY_SOC_SIGNAL(OT_AON_TIMER_BITE, 0, PWRMGR, \ - OT_PWRMGR_RST, - OT_PWRMGR_RST_AON_TIMER) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 155), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 156), + OT_EG_SOC_SIGNAL(OT_AON_TIMER_WKUP, 0, PWRMGR, \ + OT_PWRMGR_WKUP, OT_PWRMGR_WAKEUP_AON_TIMER), + OT_EG_SOC_SIGNAL(OT_AON_TIMER_BITE, 0, PWRMGR, \ + OT_PWRMGR_RST, OT_EG_RESET_AON_TIMER) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("pclk", OT_EARLGREY_AON_CLK_HZ) + IBEX_DEV_UINT_PROP("pclk", OT_EG_AON_CLK_HZ) ), }, - [OT_EARLGREY_SOC_DEV_AST] = { + [OT_EG_SOC_DEV_AST] = { .type = TYPE_OT_AST_EG, .memmap = MEMMAPENTRIES( { 0x40480000u, 0x400u } ), }, - [OT_EARLGREY_SOC_DEV_SENSOR_CTRL] = { + [OT_EG_SOC_DEV_SENSOR_CTRL] = { .type = TYPE_OT_SENSOR, .memmap = MEMMAPENTRIES( { 0x40490000u, 0x40u } ), }, - [OT_EARLGREY_SOC_DEV_SRAM_RET_CTRL] = { + [OT_EG_SOC_DEV_SRAM_RET_CTRL] = { .type = TYPE_OT_SRAM_CTRL, .instance = 0, .memmap = MEMMAPENTRIES( @@ -635,94 +651,94 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x40600000u, 0x1000u } ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("size", 0x1000u), IBEX_DEV_STRING_PROP("ot_id", "ret") ), }, - [OT_EARLGREY_SOC_DEV_FLASH_CTRL] = { + [OT_EG_SOC_DEV_FLASH_CTRL] = { .type = TYPE_OT_FLASH, - .cfg = &ot_earlgrey_soc_flash_ctrl_configure, + .cfg = &ot_eg_soc_flash_ctrl_configure, .memmap = MEMMAPENTRIES( { 0x41000000u, 0x1000u }, { 0x41008000u, 0x1000u }, { 0x20000000u, 0x100000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 159), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 160), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 161), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 162), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 163), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 164) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 159), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 160), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 161), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 162), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 163), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 164) ), }, - [OT_EARLGREY_SOC_DEV_AES] = { + [OT_EG_SOC_DEV_AES] = { .type = TYPE_OT_AES, .memmap = MEMMAPENTRIES( { 0x41100000u, 0x100u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_AES) + OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_AES) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("edn", EDN0) + OT_EG_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 5u) ), }, - [OT_EARLGREY_SOC_DEV_HMAC] = { + [OT_EG_SOC_DEV_HMAC] = { .type = TYPE_OT_HMAC, .memmap = MEMMAPENTRIES( { 0x41110000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 165), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 166), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 167), - OT_EARLGREY_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_HMAC) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 165), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 166), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 167), + OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_HMAC) ), }, - [OT_EARLGREY_SOC_DEV_KMAC] = { + [OT_EG_SOC_DEV_KMAC] = { .type = TYPE_OT_KMAC, .memmap = MEMMAPENTRIES( { 0x41120000u, 0x1000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 168), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 169), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 170) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 168), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 169), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 170) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("edn", EDN0) + OT_EG_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 3u), IBEX_DEV_UINT_PROP("num-app", 3u) ), }, - [OT_EARLGREY_SOC_DEV_OTBN] = { + [OT_EG_SOC_DEV_OTBN] = { .type = TYPE_OT_OTBN, .memmap = MEMMAPENTRIES( { 0x41130000u, 0x10000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 171), - OT_EARLGREY_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_OTBN) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 171), + OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_OTBN) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("edn-u", EDN0), - OT_EARLGREY_SOC_DEVLINK("edn-r", EDN1) + OT_EG_SOC_DEVLINK("edn-u", EDN0), + OT_EG_SOC_DEVLINK("edn-r", EDN1) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-u-ep", 6u), IBEX_DEV_UINT_PROP("edn-r-ep", 0u) ), }, - [OT_EARLGREY_SOC_DEV_KEYMGR] = { + [OT_EG_SOC_DEV_KEYMGR] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-keymgr", .cfg = &ibex_unimp_configure, @@ -730,73 +746,73 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x41140000u, 0x100u } ), }, - [OT_EARLGREY_SOC_DEV_CSRNG] = { + [OT_EG_SOC_DEV_CSRNG] = { .type = TYPE_OT_CSRNG, .memmap = MEMMAPENTRIES( { 0x41150000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 173), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 174), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 175), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 176) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 173), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 174), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 175), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 176) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("random_src", ENTROPY_SRC), - OT_EARLGREY_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("random_src", ENTROPY_SRC), + OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), }, - [OT_EARLGREY_SOC_DEV_ENTROPY_SRC] = { + [OT_EG_SOC_DEV_ENTROPY_SRC] = { .type = TYPE_OT_ENTROPY_SRC, .memmap = MEMMAPENTRIES( { 0x41160000u, 0x100u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 177), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 178), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 179), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 180) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 177), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 178), + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 179), + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 180) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("ast", AST), - OT_EARLGREY_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("ast", AST), + OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), }, - [OT_EARLGREY_SOC_DEV_EDN0] = { + [OT_EG_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, .instance = 0, .memmap = MEMMAPENTRIES( { 0x41170000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 181), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 182) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 181), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 182) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("csrng", CSRNG) + OT_EG_SOC_DEVLINK("csrng", CSRNG) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("csrng-app", 0u) ), }, - [OT_EARLGREY_SOC_DEV_EDN1] = { + [OT_EG_SOC_DEV_EDN1] = { .type = TYPE_OT_EDN, .instance = 1, .memmap = MEMMAPENTRIES( { 0x41180000u, 0x80u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 183), - OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 184) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 183), + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 184) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("csrng", CSRNG) + OT_EG_SOC_DEVLINK("csrng", CSRNG) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("csrng-app", 1u) ), }, - [OT_EARLGREY_SOC_DEV_SRAM_MAIN_CTRL] = { + [OT_EG_SOC_DEV_SRAM_MAIN_CTRL] = { .type = TYPE_OT_SRAM_CTRL, .instance = 1, .memmap = MEMMAPENTRIES( @@ -804,14 +820,14 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x10000000u, 0x20000u } ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("size", 0x20000u), IBEX_DEV_STRING_PROP("ot_id", "ram") ), }, - [OT_EARLGREY_SOC_DEV_ROM_CTRL] = { + [OT_EG_SOC_DEV_ROM_CTRL] = { .type = TYPE_OT_ROM_CTRL, .name = "ot-rom_ctrl", .memmap = MEMMAPENTRIES( @@ -819,13 +835,13 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x00008000u, 0x8000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, \ + OT_EG_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, \ OT_PWRMGR_ROM_GOOD, 0), - OT_EARLGREY_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, \ + OT_EG_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, \ OT_PWRMGR_ROM_DONE, 0) ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("kmac", KMAC) + OT_EG_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("ot_id", "rom"), @@ -833,19 +849,19 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { IBEX_DEV_UINT_PROP("kmac-app", 2u) ), }, - [OT_EARLGREY_SOC_DEV_IBEX_WRAPPER] = { + [OT_EG_SOC_DEV_IBEX_WRAPPER] = { .type = TYPE_OT_IBEX_WRAPPER_EG, .memmap = MEMMAPENTRIES( { 0x411f0000u, 0x100u } ), .link = IBEXDEVICELINKDEFS( - OT_EARLGREY_SOC_DEVLINK("edn", EDN0) + OT_EG_SOC_DEVLINK("edn", EDN0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("edn-ep", 7u) ), }, - [OT_EARLGREY_SOC_DEV_RV_DM] = { + [OT_EG_SOC_DEV_RV_DM] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-rv_dm", .cfg = &ibex_unimp_configure, @@ -853,13 +869,13 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { { 0x41200000u, 0x4u } ), }, - [OT_EARLGREY_SOC_DEV_PLIC] = { + [OT_EG_SOC_DEV_PLIC] = { .type = TYPE_SIFIVE_PLIC, .memmap = MEMMAPENTRIES( { 0x48000000u, 0x8000000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EARLGREY_SOC_GPIO(1, HART, IRQ_M_EXT) + OT_EG_SOC_GPIO(1, HART, IRQ_M_EXT) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("hart-config", "M"), @@ -879,35 +895,35 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = { /* clang-format on */ }; -enum OtEarlGreyBoardDevice { - OT_EARLGREY_BOARD_DEV_SOC, - OT_EARLGREY_BOARD_DEV_FLASH, - _OT_EARLGREY_BOARD_DEV_COUNT, +enum OtEGBoardDevice { + OT_EG_BOARD_DEV_SOC, + OT_EG_BOARD_DEV_FLASH, + OT_EG_BOARD_DEV_COUNT, }; /* ------------------------------------------------------------------------ */ /* Type definitions */ /* ------------------------------------------------------------------------ */ -struct OtEarlGreySoCClass { +struct OtEGSoCClass { DeviceClass parent_class; DeviceRealize parent_realize; ResettablePhases parent_phases; }; -struct OtEarlGreySoCState { +struct OtEGSoCState { SysBusDevice parent_obj; DeviceState **devices; }; -struct OtEarlGreyBoardState { +struct OtEGBoardState { DeviceState parent_obj; DeviceState **devices; }; -struct OtEarlGreyMachineState { +struct OtEGMachineState { MachineState parent_obj; bool no_epmp_cfg; @@ -917,7 +933,7 @@ struct OtEarlGreyMachineState { /* Device Configuration */ /* ------------------------------------------------------------------------ */ -static void ot_earlgrey_soc_flash_ctrl_configure( +static void ot_eg_soc_flash_ctrl_configure( DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) { DriveInfo *dinfo = drive_get(IF_MTD, 1, 0); @@ -930,10 +946,10 @@ static void ot_earlgrey_soc_flash_ctrl_configure( } } -static void ot_earlgrey_soc_hart_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) +static void ot_eg_soc_hart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent) { - OtEarlGreyMachineState *ms = RISCV_OT_EARLGREY_MACHINE(qdev_get_machine()); + OtEGMachineState *ms = RISCV_OT_EG_MACHINE(qdev_get_machine()); QList *pmp_cfg, *pmp_addr; (void)def; (void)parent; @@ -944,21 +960,21 @@ static void ot_earlgrey_soc_hart_configure( } pmp_cfg = qlist_new(); - for (unsigned ix = 0; ix < ARRAY_SIZE(ot_earlgrey_pmp_cfgs); ix++) { - qlist_append_int(pmp_cfg, ot_earlgrey_pmp_cfgs[ix]); + for (unsigned ix = 0; ix < ARRAY_SIZE(ot_eg_pmp_cfgs); ix++) { + qlist_append_int(pmp_cfg, ot_eg_pmp_cfgs[ix]); } qdev_prop_set_array(dev, "pmp_cfg", pmp_cfg); pmp_addr = qlist_new(); - for (unsigned ix = 0; ix < ARRAY_SIZE(ot_earlgrey_pmp_addrs); ix++) { - qlist_append_int(pmp_addr, ot_earlgrey_pmp_addrs[ix]); + for (unsigned ix = 0; ix < ARRAY_SIZE(ot_eg_pmp_addrs); ix++) { + qlist_append_int(pmp_addr, ot_eg_pmp_addrs[ix]); } qdev_prop_set_array(dev, "pmp_addr", pmp_addr); - qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_EARLGREY_MSECCFG); + qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_EG_MSECCFG); } -static void ot_earlgrey_soc_otp_ctrl_configure( +static void ot_eg_soc_otp_ctrl_configure( DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) { DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); @@ -971,8 +987,8 @@ static void ot_earlgrey_soc_otp_ctrl_configure( } } -static void ot_earlgrey_soc_uart_configure( - DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) +static void ot_eg_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent) { (void)def; (void)parent; @@ -983,114 +999,117 @@ static void ot_earlgrey_soc_uart_configure( /* SoC */ /* ------------------------------------------------------------------------ */ -static void ot_earlgrey_soc_reset_hold(Object *obj) +static void ot_eg_soc_reset_hold(Object *obj) { - OtEarlGreySoCClass *c = RISCV_OT_EARLGREY_SOC_GET_CLASS(obj); - OtEarlGreySoCState *s = RISCV_OT_EARLGREY_SOC(obj); + OtEGSoCClass *c = RISCV_OT_EG_SOC_GET_CLASS(obj); + OtEGSoCState *s = RISCV_OT_EG_SOC(obj); if (c->parent_phases.hold) { c->parent_phases.hold(obj); } /* keep ROM_CTRL in reset, we'll release it last */ - resettable_assert_reset(OBJECT(s->devices[OT_EARLGREY_SOC_DEV_ROM_CTRL]), + resettable_assert_reset(OBJECT(s->devices[OT_EG_SOC_DEV_ROM_CTRL]), RESET_TYPE_COLD); /* - * leave hart on reset - * power manager should release it once ROM has been validated + * Power-On-Reset: leave hart on reset + * PowerManager takes care of managing Ibex reset when ready + * + * Note that an initial, extra single reset cycle (assert/release) is + * performed from the generic #riscv_cpu_realize function on machine + * realization. */ - CPUState *cs = CPU(s->devices[OT_EARLGREY_SOC_DEV_HART]); + CPUState *cs = CPU(s->devices[OT_EG_SOC_DEV_HART]); resettable_assert_reset(OBJECT(cs), RESET_TYPE_COLD); } -static void ot_earlgrey_soc_reset_exit(Object *obj) +static void ot_eg_soc_reset_exit(Object *obj) { - OtEarlGreySoCClass *c = RISCV_OT_EARLGREY_SOC_GET_CLASS(obj); - OtEarlGreySoCState *s = RISCV_OT_EARLGREY_SOC(obj); + OtEGSoCClass *c = RISCV_OT_EG_SOC_GET_CLASS(obj); + OtEGSoCState *s = RISCV_OT_EG_SOC(obj); if (c->parent_phases.exit) { c->parent_phases.exit(obj); } /* let ROM_CTRL get out of reset now */ - resettable_release_reset(OBJECT(s->devices[OT_EARLGREY_SOC_DEV_ROM_CTRL]), + resettable_release_reset(OBJECT(s->devices[OT_EG_SOC_DEV_ROM_CTRL]), RESET_TYPE_COLD); } -static void ot_earlgrey_soc_realize(DeviceState *dev, Error **errp) +static void ot_eg_soc_realize(DeviceState *dev, Error **errp) { - OtEarlGreySoCState *s = RISCV_OT_EARLGREY_SOC(dev); + OtEGSoCState *s = RISCV_OT_EG_SOC(dev); (void)errp; /* Link, define properties and realize devices, then connect GPIOs */ BusState *bus = sysbus_get_default(); ibex_configure_devices_with_id(s->devices, bus, "ot_id", "", false, - ot_earlgrey_soc_devices, - ARRAY_SIZE(ot_earlgrey_soc_devices)); + 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_earlgrey_soc_devices, - ARRAY_SIZE(ot_earlgrey_soc_devices)); + ibex_map_devices(s->devices, mrs, ot_eg_soc_devices, + ARRAY_SIZE(ot_eg_soc_devices)); /* load kernel if provided */ ibex_load_kernel(NULL); } -static void ot_earlgrey_soc_init(Object *obj) +static void ot_eg_soc_init(Object *obj) { - OtEarlGreySoCState *s = RISCV_OT_EARLGREY_SOC(obj); + OtEGSoCState *s = RISCV_OT_EG_SOC(obj); - s->devices = - ibex_create_devices(ot_earlgrey_soc_devices, - ARRAY_SIZE(ot_earlgrey_soc_devices), DEVICE(s)); + s->devices = ibex_create_devices(ot_eg_soc_devices, + ARRAY_SIZE(ot_eg_soc_devices), DEVICE(s)); } -static void ot_earlgrey_soc_class_init(ObjectClass *oc, void *data) +static void ot_eg_soc_class_init(ObjectClass *oc, void *data) { - OtEarlGreySoCClass *sc = RISCV_OT_EARLGREY_SOC_CLASS(oc); + OtEGSoCClass *sc = RISCV_OT_EG_SOC_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); ResettableClass *rc = RESETTABLE_CLASS(dc); (void)data; - resettable_class_set_parent_phases(rc, NULL, &ot_earlgrey_soc_reset_hold, - &ot_earlgrey_soc_reset_exit, + resettable_class_set_parent_phases(rc, NULL, &ot_eg_soc_reset_hold, + &ot_eg_soc_reset_exit, &sc->parent_phases); - dc->realize = &ot_earlgrey_soc_realize; + dc->realize = &ot_eg_soc_realize; dc->user_creatable = false; } -static const TypeInfo ot_earlgrey_soc_type_info = { - .name = TYPE_RISCV_OT_EARLGREY_SOC, +static const TypeInfo ot_eg_soc_type_info = { + .name = TYPE_RISCV_OT_EG_SOC, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(OtEarlGreySoCState), - .instance_init = &ot_earlgrey_soc_init, - .class_init = &ot_earlgrey_soc_class_init, - .class_size = sizeof(OtEarlGreySoCClass), + .instance_size = sizeof(OtEGSoCState), + .instance_init = &ot_eg_soc_init, + .class_init = &ot_eg_soc_class_init, + .class_size = sizeof(OtEGSoCClass), }; -static void ot_earlgrey_soc_register_types(void) +static void ot_eg_soc_register_types(void) { - type_register_static(&ot_earlgrey_soc_type_info); + type_register_static(&ot_eg_soc_type_info); } -type_init(ot_earlgrey_soc_register_types); +type_init(ot_eg_soc_register_types); /* ------------------------------------------------------------------------ */ /* Board */ /* ------------------------------------------------------------------------ */ -static void ot_earlgrey_board_realize(DeviceState *dev, Error **errp) +static void ot_eg_board_realize(DeviceState *dev, Error **errp) { - OtEarlGreyBoardState *board = RISCV_OT_EARLGREY_BOARD(dev); + OtEGBoardState *board = RISCV_OT_EG_BOARD(dev); - DeviceState *soc = board->devices[OT_EARLGREY_BOARD_DEV_SOC]; + DeviceState *soc = board->devices[OT_EG_BOARD_DEV_SOC]; object_property_add_child(OBJECT(board), "soc", OBJECT(soc)); sysbus_realize_and_unref(SYS_BUS_DEVICE(soc), &error_fatal); DeviceState *spihost = - RISCV_OT_EARLGREY_SOC(soc)->devices[OT_EARLGREY_SOC_DEV_SPI_HOST0]; - DeviceState *flash = board->devices[OT_EARLGREY_BOARD_DEV_FLASH]; + RISCV_OT_EG_SOC(soc)->devices[OT_EG_SOC_DEV_SPI_HOST0]; + DeviceState *flash = board->devices[OT_EG_BOARD_DEV_FLASH]; BusState *spibus = qdev_get_child_bus(spihost, "spi0"); g_assert(spibus); @@ -1106,107 +1125,103 @@ static void ot_earlgrey_board_realize(DeviceState *dev, Error **errp) qdev_connect_gpio_out_named(spihost, SSI_GPIO_CS, 0, cs); } -static void ot_earlgrey_board_init(Object *obj) +static void ot_eg_board_init(Object *obj) { - OtEarlGreyBoardState *s = RISCV_OT_EARLGREY_BOARD(obj); + OtEGBoardState *s = RISCV_OT_EG_BOARD(obj); - s->devices = g_new0(DeviceState *, _OT_EARLGREY_BOARD_DEV_COUNT); - s->devices[OT_EARLGREY_BOARD_DEV_SOC] = - qdev_new(TYPE_RISCV_OT_EARLGREY_SOC); - s->devices[OT_EARLGREY_BOARD_DEV_FLASH] = qdev_new("is25wp128"); + s->devices = g_new0(DeviceState *, OT_EG_BOARD_DEV_COUNT); + s->devices[OT_EG_BOARD_DEV_SOC] = qdev_new(TYPE_RISCV_OT_EG_SOC); + s->devices[OT_EG_BOARD_DEV_FLASH] = qdev_new("is25wp128"); } -static void ot_earlgrey_board_class_init(ObjectClass *oc, void *data) +static void ot_eg_board_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); (void)data; - dc->realize = &ot_earlgrey_board_realize; + dc->realize = &ot_eg_board_realize; } -static const TypeInfo ot_earlgrey_board_type_info = { - .name = TYPE_RISCV_OT_EARLGREY_BOARD, +static const TypeInfo ot_eg_board_type_info = { + .name = TYPE_RISCV_OT_EG_BOARD, .parent = TYPE_DEVICE, - .instance_size = sizeof(OtEarlGreyBoardState), - .instance_init = &ot_earlgrey_board_init, - .class_init = &ot_earlgrey_board_class_init, + .instance_size = sizeof(OtEGBoardState), + .instance_init = &ot_eg_board_init, + .class_init = &ot_eg_board_class_init, }; -static void ot_earlgrey_board_register_types(void) +static void ot_eg_board_register_types(void) { - type_register_static(&ot_earlgrey_board_type_info); + type_register_static(&ot_eg_board_type_info); } -type_init(ot_earlgrey_board_register_types); +type_init(ot_eg_board_register_types); /* ------------------------------------------------------------------------ */ /* Machine */ /* ------------------------------------------------------------------------ */ -static bool ot_earlgrey_machine_get_no_epmp_cfg(Object *obj, Error **errp) +static bool ot_eg_machine_get_no_epmp_cfg(Object *obj, Error **errp) { - OtEarlGreyMachineState *s = RISCV_OT_EARLGREY_MACHINE(obj); + OtEGMachineState *s = RISCV_OT_EG_MACHINE(obj); (void)errp; return s->no_epmp_cfg; } -static void -ot_earlgrey_machine_set_no_epmp_cfg(Object *obj, bool value, Error **errp) +static void ot_eg_machine_set_no_epmp_cfg(Object *obj, bool value, Error **errp) { - OtEarlGreyMachineState *s = RISCV_OT_EARLGREY_MACHINE(obj); + OtEGMachineState *s = RISCV_OT_EG_MACHINE(obj); (void)errp; s->no_epmp_cfg = value; } -static void ot_earlgrey_machine_instance_init(Object *obj) +static void ot_eg_machine_instance_init(Object *obj) { - OtEarlGreyMachineState *s = RISCV_OT_EARLGREY_MACHINE(obj); + OtEGMachineState *s = RISCV_OT_EG_MACHINE(obj); s->no_epmp_cfg = false; - object_property_add_bool(obj, "no-epmp-cfg", - &ot_earlgrey_machine_get_no_epmp_cfg, - &ot_earlgrey_machine_set_no_epmp_cfg); + object_property_add_bool(obj, "no-epmp-cfg", &ot_eg_machine_get_no_epmp_cfg, + &ot_eg_machine_set_no_epmp_cfg); object_property_set_description(obj, "no-epmp-cfg", "Skip default ePMP configuration"); } -static void ot_earlgrey_machine_init(MachineState *state) +static void ot_eg_machine_init(MachineState *state) { - DeviceState *dev = qdev_new(TYPE_RISCV_OT_EARLGREY_BOARD); + DeviceState *dev = qdev_new(TYPE_RISCV_OT_EG_BOARD); object_property_add_child(OBJECT(state), "board", OBJECT(dev)); qdev_realize(dev, NULL, &error_fatal); } -static void ot_earlgrey_machine_class_init(ObjectClass *oc, void *data) +static void ot_eg_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); (void)data; mc->desc = "RISC-V Board compatible with OpenTitan EarlGrey FPGA platform"; - mc->init = ot_earlgrey_machine_init; + mc->init = ot_eg_machine_init; mc->max_cpus = 1u; - mc->default_cpu_type = - ot_earlgrey_soc_devices[OT_EARLGREY_SOC_DEV_HART].type; + mc->default_cpu_type = ot_eg_soc_devices[OT_EG_SOC_DEV_HART].type; const IbexDeviceDef *sram = - &ot_earlgrey_soc_devices[OT_EARLGREY_SOC_DEV_SRAM_MAIN_CTRL]; + &ot_eg_soc_devices[OT_EG_SOC_DEV_SRAM_MAIN_CTRL]; mc->default_ram_id = sram->type; mc->default_ram_size = sram->memmap[1].size; } -static const TypeInfo ot_earlgrey_machine_type_info = { - .name = TYPE_RISCV_OT_EARLGREY_MACHINE, +static const TypeInfo ot_eg_machine_type_info = { + .name = TYPE_RISCV_OT_EG_MACHINE, .parent = TYPE_MACHINE, - .instance_size = sizeof(OtEarlGreyMachineState), - .instance_init = &ot_earlgrey_machine_instance_init, - .class_init = &ot_earlgrey_machine_class_init, + .instance_size = sizeof(OtEGMachineState), + .instance_init = &ot_eg_machine_instance_init, + .class_init = &ot_eg_machine_class_init, }; -static void ot_earlgrey_machine_register_types(void) +static void ot_eg_machine_register_types(void) { - type_register_static(&ot_earlgrey_machine_type_info); + type_register_static(&ot_eg_machine_type_info); } -type_init(ot_earlgrey_machine_register_types); +type_init(ot_eg_machine_register_types); diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events index aeb3e48cdc91..d77b54615bb4 100644 --- a/hw/riscv/trace-events +++ b/hw/riscv/trace-events @@ -1,5 +1,8 @@ -# Debug Module Interface -riscv_dmi_error(const char *func, int line, const char *msg) "%s:%d %s" -riscv_dmi_info(const char *func, int line, const char *msg, uint32_t val) "%s:%d %s 0x%08x" -riscv_dmi_register_dm(unsigned count, uint64_t first, uint64_t last, bool ok) "#%u 0x%" PRIx64 "..0x%" PRIx64 ": %u" -riscv_dmi_vm_state_change(const char *name, unsigned state) "VM state: %s[%u]" +# See documentation at docs/devel/tracing.rst + +# Debug Transport Module +riscv_dtm_dtmcs_reset(void) "" +riscv_dtm_error(const char *func, int line, const char *msg) "%s:%d %s" +riscv_dtm_info(const char *func, int line, const char *msg, uint32_t val) "%s:%d %s 0x%08x" +riscv_dtm_register_dm(unsigned count, uint64_t first, uint64_t last, bool ok) "#%u 0x%" PRIx64 "..0x%" PRIx64 ": %u" +riscv_dtm_vm_state_change(const char *name, unsigned state) "VM state: %s[%u]" diff --git a/include/hw/opentitan/ot_common.h b/include/hw/opentitan/ot_common.h index 7edb299eddb5..cceda7662ba2 100644 --- a/include/hw/opentitan/ot_common.h +++ b/include/hw/opentitan/ot_common.h @@ -23,10 +23,18 @@ #ifndef HW_OPENTITAN_OT_COMMON_H #define HW_OPENTITAN_OT_COMMON_H +#include "qemu/timer.h" #include "chardev/char-fe.h" #include "exec/memory.h" #include "hw/core/cpu.h" +/* ------------------------------------------------------------------------ */ +/* Timer */ +/* ------------------------------------------------------------------------ */ + +/* QEMU virtual timer to use for OpenTitan devices */ +#define OT_VIRTUAL_CLOCK QEMU_CLOCK_VIRTUAL_RT + /* ------------------------------------------------------------------------ */ /* Multi-bit boolean values */ /* ------------------------------------------------------------------------ */ diff --git a/include/hw/opentitan/ot_mbx.h b/include/hw/opentitan/ot_mbx.h index 59c38bdea0ac..3a9661d84445 100644 --- a/include/hw/opentitan/ot_mbx.h +++ b/include/hw/opentitan/ot_mbx.h @@ -37,8 +37,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(OtMbxState, OT_MBX) #define OT_MBX_SYS_REGS_COUNT 6u #define OT_MBX_HOST_APERTURE \ - DIV_ROUND_UP((OT_MBX_HOST_REGS_COUNT * sizeof(uint32_t)), 0x10u) + ROUND_UP((OT_MBX_HOST_REGS_COUNT * sizeof(uint32_t)), 0x10u) #define OT_MBX_SYS_APERTURE \ - DIV_ROUND_UP((OT_MBX_SYS_REGS_COUNT * sizeof(uint32_t)), 0x10u) + ROUND_UP((OT_MBX_SYS_REGS_COUNT * sizeof(uint32_t)), 0x10u) #endif /* HW_OPENTITAN_OT_MBX_H */ diff --git a/include/hw/opentitan/ot_pwrmgr.h b/include/hw/opentitan/ot_pwrmgr.h index e3b47c1847f9..44fb15820535 100644 --- a/include/hw/opentitan/ot_pwrmgr.h +++ b/include/hw/opentitan/ot_pwrmgr.h @@ -32,7 +32,14 @@ #include "qom/object.h" #define TYPE_OT_PWRMGR "ot-pwrmgr" -OBJECT_DECLARE_SIMPLE_TYPE(OtPwrMgrState, OT_PWRMGR) +OBJECT_DECLARE_TYPE(OtPwrMgrState, OtPwrMgrClass, OT_PWRMGR) + +/* Supported PowerManager versions */ +typedef enum { + OT_PWMGR_VERSION_EG, + OT_PWMGR_VERSION_DJ, + OT_PWMGR_VERSION_COUNT, +} OtPwrMgrVersion; /* Match PWRMGR_PARAM_*_WKUP_REQ_IDX definitions */ typedef enum { @@ -45,12 +52,6 @@ typedef enum { OT_PWRMGR_WAKEUP_COUNT, } OtPwrMgrWakeup; -typedef enum { - OT_PWRMGR_RST_SYSRST, - OT_PWRMGR_RST_AON_TIMER, /* watchdog bite */ - OT_PWRMGR_RST_COUNT, -} OtPwrMgrRst; - /* output lines */ #define OT_PWRMGR_LC_REQ TYPE_OT_PWRMGR "-lc-req" #define OT_PWRMGR_OTP_REQ TYPE_OT_PWRMGR "-otp-req" @@ -67,4 +68,7 @@ typedef enum { #define OT_PWRMGR_ROM_GOOD TYPE_OT_PWRMGR "-rom-good" #define OT_PWRMGR_ROM_DONE TYPE_OT_PWRMGR "-rom-done" +/* custom extension */ +#define OT_PWRMGR_HOLDON_FETCH TYPE_OT_PWRMGR "-holdon-fetch" + #endif /* HW_OPENTITAN_OT_PWRMGR_H */ diff --git a/include/hw/opentitan/ot_random_src.h b/include/hw/opentitan/ot_random_src.h index 86da50834558..7313130b5e8d 100644 --- a/include/hw/opentitan/ot_random_src.h +++ b/include/hw/opentitan/ot_random_src.h @@ -71,6 +71,8 @@ struct OtRandomSrcIfClass { * @random the buffer to fill in with random data * @fips on success, updated to @true if random data are FIPS-compliant * @return 0 on success, + * >=1 if the source is initializing, if >1, indicates the hint on + * how many ns to wait before retrying, * -1 if the random source is not available, i.e. if the module is * not enabled or if the selected route is not the HW one, * -2 if the generation ID does not match and execution cannot diff --git a/include/hw/riscv/dmi.h b/include/hw/riscv/dtm.h similarity index 76% rename from include/hw/riscv/dmi.h rename to include/hw/riscv/dtm.h index 7bbc6acf0632..c7eb9752a865 100644 --- a/include/hw/riscv/dmi.h +++ b/include/hw/riscv/dtm.h @@ -1,7 +1,7 @@ /* - * QEMU RISC-V Debug Module Interface and Controller + * QEMU RISC-V Debug Tranport Module * - * Copyright (c) 2022-2023 Rivos, Inc. + * Copyright (c) 2022-2024 Rivos, Inc. * Author(s): * Emmanuel Blot * @@ -24,27 +24,27 @@ * THE SOFTWARE. */ -#ifndef HW_RISCV_DMI_H -#define HW_RISCV_DMI_H +#ifndef HW_RISCV_DTM_H +#define HW_RISCV_DTM_H #include "exec/hwaddr.h" #include "hw/riscv/debug.h" -#define TYPE_RISCV_DMI "riscv-dmi" -OBJECT_DECLARE_SIMPLE_TYPE(RISCVDMIState, RISCV_DMI) +#define TYPE_RISCV_DTM "riscv.dtm" +OBJECT_DECLARE_SIMPLE_TYPE(RISCVDTMState, RISCV_DTM) /** - * Register a debug module on the Debug Module Interface. + * Register a debug module on the Debug Transport Module. * It is valid to register the same module multiple time, as long as base_addr * and size are not modified. * - * @dev the DMI instance + * @dev the DTM instance * @dmif the DM to register * @base_addr the address of the first DM register * @size the count of DM registers - * @return @c true if DMI is enabled, @c false otherwise + * @return @c true if DTM is enabled, @c false otherwise */ -bool riscv_dmi_register_dm(DeviceState *dev, RISCVDebugDeviceState *dmif, +bool riscv_dtm_register_dm(DeviceState *dev, RISCVDebugDeviceState *dmif, hwaddr base_addr, hwaddr size); -#endif /* HW_RISCV_DMI_H */ +#endif /* HW_RISCV_DTM_H */ diff --git a/include/hw/riscv/ibex_irq.h b/include/hw/riscv/ibex_irq.h index da0fbc52756e..eb9f3b8a3918 100644 --- a/include/hw/riscv/ibex_irq.h +++ b/include/hw/riscv/ibex_irq.h @@ -76,6 +76,13 @@ static inline void ibex_qdev_init_irq(Object *obj, IbexIRQ *irq, qdev_init_gpio_out_named(DEVICE(obj), &irq->irq, name, 1); } +static inline void ibex_qdev_init_irq_default(Object *obj, IbexIRQ *irq, + const char *name, int level) +{ + irq->level = level; + qdev_init_gpio_out_named(DEVICE(obj), &irq->irq, name, 1); +} + static inline void ibex_qdev_init_irqs(Object *obj, IbexIRQ *irqs, const char *name, unsigned count) { diff --git a/include/hw/riscv/ot_darjeeling.h b/include/hw/riscv/ot_darjeeling.h index 3e202e405896..f86840819dea 100644 --- a/include/hw/riscv/ot_darjeeling.h +++ b/include/hw/riscv/ot_darjeeling.h @@ -25,15 +25,13 @@ #include "qom/object.h" -#define TYPE_RISCV_OT_DARJEELING_MACHINE MACHINE_TYPE_NAME("ot-darjeeling") -OBJECT_DECLARE_SIMPLE_TYPE(OtDarjeelingMachineState, - RISCV_OT_DARJEELING_MACHINE) +#define TYPE_RISCV_OT_DJ_MACHINE MACHINE_TYPE_NAME("ot-darjeeling") +OBJECT_DECLARE_SIMPLE_TYPE(OtDjMachineState, RISCV_OT_DJ_MACHINE) -#define TYPE_RISCV_OT_DARJEELING_BOARD "riscv.ot_darjeeling.board" -OBJECT_DECLARE_SIMPLE_TYPE(OtDarjeelingBoardState, RISCV_OT_DARJEELING_BOARD) +#define TYPE_RISCV_OT_DJ_BOARD "riscv.ot_darjeeling.board" +OBJECT_DECLARE_SIMPLE_TYPE(OtDjBoardState, RISCV_OT_DJ_BOARD) -#define TYPE_RISCV_OT_DARJEELING_SOC "riscv.ot_darjeeling.soc" -OBJECT_DECLARE_TYPE(OtDarjeelingSoCState, OtDarjeelingSoCClass, - RISCV_OT_DARJEELING_SOC) +#define TYPE_RISCV_OT_DJ_SOC "riscv.ot_darjeeling.soc" +OBJECT_DECLARE_TYPE(OtDjSoCState, OtDjSoCClass, RISCV_OT_DJ_SOC) #endif /* HW_RISCV_OT_DARJEELING_H */ diff --git a/include/hw/riscv/ot_earlgrey.h b/include/hw/riscv/ot_earlgrey.h index 4c04a10bd83b..cb85abb36674 100644 --- a/include/hw/riscv/ot_earlgrey.h +++ b/include/hw/riscv/ot_earlgrey.h @@ -24,14 +24,13 @@ #include "qom/object.h" -#define TYPE_RISCV_OT_EARLGREY_MACHINE MACHINE_TYPE_NAME("ot-earlgrey") -OBJECT_DECLARE_SIMPLE_TYPE(OtEarlGreyMachineState, RISCV_OT_EARLGREY_MACHINE) +#define TYPE_RISCV_OT_EG_MACHINE MACHINE_TYPE_NAME("ot-earlgrey") +OBJECT_DECLARE_SIMPLE_TYPE(OtEGMachineState, RISCV_OT_EG_MACHINE) -#define TYPE_RISCV_OT_EARLGREY_BOARD "riscv.ot_earlgrey.board" -OBJECT_DECLARE_SIMPLE_TYPE(OtEarlGreyBoardState, RISCV_OT_EARLGREY_BOARD) +#define TYPE_RISCV_OT_EG_BOARD "riscv.ot_earlgrey.board" +OBJECT_DECLARE_SIMPLE_TYPE(OtEGBoardState, RISCV_OT_EG_BOARD) -#define TYPE_RISCV_OT_EARLGREY_SOC "riscv.ot_earlgrey.soc" -OBJECT_DECLARE_TYPE(OtEarlGreySoCState, OtEarlGreySoCClass, - RISCV_OT_EARLGREY_SOC) +#define TYPE_RISCV_OT_EG_SOC "riscv.ot_earlgrey.soc" +OBJECT_DECLARE_TYPE(OtEGSoCState, OtEGSoCClass, RISCV_OT_EG_SOC) #endif /* HW_RISCV_OT_EARLGREY_H */ diff --git a/jtag/jtag_bitbang.c b/jtag/jtag_bitbang.c index 4d3c1be2e7bb..8d7e62748a99 100644 --- a/jtag/jtag_bitbang.c +++ b/jtag/jtag_bitbang.c @@ -36,6 +36,7 @@ #include "qemu/module.h" #include "qemu/sockets.h" #include "qapi/error.h" +#include "qom/object.h" #include "chardev/char-fe.h" #include "chardev/char.h" #include "exec/gdbstub.h" @@ -43,6 +44,7 @@ #include "exec/jtagstub.h" #include "hw/boards.h" #include "hw/cpu/cluster.h" +#include "hw/resettable.h" #include "monitor/monitor.h" #include "semihosting/semihost.h" #include "sysemu/hw_accel.h" @@ -55,7 +57,9 @@ * Type definitions */ -typedef enum _TAPState { +/* clang-format off */ + +typedef enum { TEST_LOGIC_RESET, RUN_TEST_IDLE, SELECT_DR_SCAN, @@ -75,6 +79,10 @@ typedef enum _TAPState { _TAP_STATE_COUNT } TAPState; +typedef enum { TAPCTRL_BYPASS = 0, TAPCTRL_IDCODE = 1 } TAPCtrlKnownIrCodes; + +/* clang-format on */ + typedef TAPDataHandler *tapctrl_data_reg_extender_t(uint64_t value); typedef struct _TAPController { @@ -94,10 +102,8 @@ typedef struct _TAPController { size_t dr_len; /* count of meaningful bits in dr */ /* handlers */ TAPDataHandler *tdh; /* Current data register handler */ - TAPDataHandler *tdhs; /* Registered handlers */ + GHashTable *tdhtable; /* Registered handlers */ /* buffer */ - uint8_t *outbuf; /* TDO output */ - size_t outpos; /* Meaningful count of bytes in outbuf */ } TAPController; typedef struct _TAPRegisterState { @@ -111,11 +117,6 @@ typedef struct _TAPProcess { bool attached; } TAPProcess; -enum RSState { - RS_INACTIVE, - RS_IDLE, -}; - typedef struct _TAPServerState { TAPController *tap; CharBackend chr; @@ -172,15 +173,19 @@ static const char TAPFSM_NAMES[_TAP_STATE_COUNT][18U] = { NAME_FSMSTATE(EXIT2_IR), NAME_FSMSTATE(UPDATE_IR), }; +static void tapctrl_idcode_capture(TAPDataHandler *tdh); + /* Common TAP instructions */ static const TAPDataHandler tapctrl_bypass = { .name = "bypass", .length = 1, .value = 0, }; + static const TAPDataHandler tapctrl_idcode = { .name = "idcode", .length = 32, + .capture = &tapctrl_idcode_capture, }; /* @@ -194,8 +199,8 @@ static TAPServerState tapserver_state; * TAP State Machine implementation */ -static void tapctrl_dump_register(const char *msg, uint64_t value, - size_t length) +static void tapctrl_dump_register(const char *msg, const char *iname, + uint64_t value, size_t length) { char buf[80]; if (length > 64u) { @@ -208,7 +213,31 @@ static void tapctrl_dump_register(const char *msg, uint64_t value, } buf[ix] = '\0'; - trace_jtag_tapctr_dump_register(msg, value, length, buf); + if (iname) { + trace_jtag_tapctrl_idump_register(msg, iname, value, length, buf); + } else { + trace_jtag_tapctrl_dump_register(msg, value, length, buf); + } +} + +static bool tapctrl_has_data_handler(TAPController *tap, unsigned code) +{ + return (bool)g_hash_table_contains(tap->tdhtable, GINT_TO_POINTER(code)); +} + +static TAPDataHandler * +tapctrl_get_data_handler(TAPController *tap, unsigned code) +{ + TAPDataHandler *tdh; + tdh = (TAPDataHandler *)g_hash_table_lookup(tap->tdhtable, + GINT_TO_POINTER(code)); + return tdh; +} + +static void tapctrl_idcode_capture(TAPDataHandler *tdh) +{ + /* special case for ID code: opaque contains the ID code value */ + tdh->value = (uint64_t)(uintptr_t)tdh->opaque; } static void tapctrl_reset(TAPController *tap) @@ -224,54 +253,80 @@ static void tapctrl_reset(TAPController *tap) tap->ir_hold = 0b01; tap->dr = 0u; tap->dr_len = 0u; - tap->tdh = &tap->tdhs[tap->ir]; - tap->outpos = 0u; + tap->tdh = tapctrl_get_data_handler(tap, TAPCTRL_IDCODE); + g_assert(tap->tdh); +} + +static void tapctrl_system_reset(TAPController *tap) +{ + Object *mc = qdev_get_machine(); + ObjectClass *oc = object_get_class(mc); + (void)tap; + + if (!object_class_dynamic_cast(oc, TYPE_RESETTABLE_INTERFACE)) { + qemu_log_mask(LOG_UNIMP, "%s: Machine %s is not resettable\n", __func__, + object_get_typename(mc)); + return; + } + + trace_jtag_tapctrl_system_reset(); + resettable_reset(mc, RESET_TYPE_COLD); } static void tapctrl_register_handler(TAPController *tap, unsigned code, const TAPDataHandler *tdh) { - memcpy(&tap->tdhs[code], tdh, sizeof(*tdh)); if (code >= (1 << tap->ir_len)) { error_setg(&error_fatal, "JTAG: Invalid IR code: 0x%x", code); + g_assert_not_reached(); + } + if (tapctrl_has_data_handler(tap, code)) { + warn_report("JTAG: IR code already registered: 0x%x", code); + /* resume and override */ } - tap->tdhs[code].name = g_strdup(tdh->name); - trace_jtag_tapctrl_register(code, tap->tdhs[code].name); + TAPDataHandler *ltdh = g_new0(TAPDataHandler, 1u); + memcpy(ltdh, tdh, sizeof(*tdh)); + ltdh->name = g_strdup(tdh->name); + g_hash_table_insert(tap->tdhtable, GINT_TO_POINTER(code), ltdh); + trace_jtag_tapctrl_register(code, ltdh->name); +} + +static void tapctrl_free_data_handler(gpointer entry) +{ + TAPDataHandler *tdh = entry; + if (!entry) { + return; + } + g_free((char *)tdh->name); + g_free(tdh); } static void tapctrl_init(TAPController *tap, size_t irlength, uint32_t idcode) { + trace_jtag_tapctrl_init(irlength, idcode); tap->ir_len = irlength; - tapctrl_reset(tap); - if (!tap->outbuf) { - tap->outbuf = g_new0(uint8_t, MAX_PACKET_LENGTH); - tap->outpos = 0; - } - if (!tap->tdhs) { + if (!tap->tdhtable) { size_t irslots = 1u << irlength; - tap->tdhs = g_new0(TAPDataHandler, irslots); - tapctrl_register_handler(tap, 0x00, &tapctrl_bypass); - tapctrl_register_handler(tap, 0x01, &tapctrl_idcode); + tap->tdhtable = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, tapctrl_free_data_handler); + tapctrl_register_handler(tap, TAPCTRL_BYPASS, &tapctrl_bypass); + tapctrl_register_handler(tap, TAPCTRL_IDCODE, &tapctrl_idcode); tapctrl_register_handler(tap, irslots - 1u, &tapctrl_bypass); - tap->tdhs[0x01].value = idcode; + /* special case for ID code: opaque store the constant idcode value */ + TAPDataHandler *tdh = tapctrl_get_data_handler(tap, TAPCTRL_IDCODE); + g_assert(tdh); + tdh->opaque = (void *)(uintptr_t)idcode; } + tapctrl_reset(tap); } static void tapctrl_deinit(TAPController *tap) { - g_free(tap->outbuf); - tap->outbuf = NULL; - if (tap->tdhs) { - unsigned irslots = 1 << tap->ir_len; - for (unsigned ix = 0; ix < irslots; ix++) { - if (tap->tdhs[ix].name) { - g_free((char *)tap->tdhs[ix].name); - tap->tdhs[ix].name = NULL; - } - } + if (tap->tdhtable) { + g_hash_table_destroy(tap->tdhtable); + tap->tdhtable = NULL; } - g_free(tap->tdhs); - tap->tdhs = NULL; + tap->tdh = NULL; } static TAPState tapctrl_get_next_state(TAPController *tap, bool tms) @@ -282,7 +337,7 @@ static TAPState tapctrl_get_next_state(TAPController *tap, bool tms) static void tapctrl_capture_ir(TAPController *tap) { - tap->ir = 0b01; + tap->ir = TAPCTRL_IDCODE; } static void tapctrl_shift_ir(TAPController *tap, bool tdi) @@ -294,30 +349,29 @@ static void tapctrl_shift_ir(TAPController *tap, bool tdi) static void tapctrl_update_ir(TAPController *tap) { tap->ir_hold = tap->ir; - tapctrl_dump_register("Update IR", tap->ir_hold, tap->ir_len); + tapctrl_dump_register("Update IR", NULL, tap->ir_hold, tap->ir_len); } -static void tapctrl_capture_dr(TAPController *tap, uint64_t value) +static void tapctrl_capture_dr(TAPController *tap) { TAPDataHandler *prev = tap->tdh; - if (value >= (1 << tap->ir_len)) { - qemu_log_mask(LOG_UNIMP, "%s: Invalid IR 0x%02x\n", __func__, - (unsigned)value); - abort(); - return; + if (tap->ir_hold >= (1 << tap->ir_len)) { + /* internal error, should never happen */ + error_setg(&error_fatal, "Invalid IR 0x%02x\n", (unsigned)tap->ir_hold); + g_assert_not_reached(); } - TAPDataHandler *tdh = &tap->tdhs[value]; - if (!tdh->length) { - qemu_log_mask(LOG_UNIMP, "%s: Unknown IR 0x%02x\n", __func__, - (unsigned)value); - abort(); + TAPDataHandler *tdh = tapctrl_get_data_handler(tap, tap->ir_hold); + if (!tdh) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown IR 0x%02x\n", __func__, + (unsigned)tap->ir_hold); + tap->dr = 0; return; } if (tdh != prev) { - trace_jtag_tapctr_select_dr(tdh->name, value); + trace_jtag_tapctrl_select_dr(tdh->name, tap->ir_hold); } tap->tdh = tdh; @@ -327,7 +381,7 @@ static void tapctrl_capture_dr(TAPController *tap, uint64_t value) tdh->capture(tdh); } tap->dr = tdh->value; - tapctrl_dump_register("Capture DR", tap->dr, tap->dr_len); + tapctrl_dump_register("Capture DR", tap->tdh->name, tap->dr, tap->dr_len); } static void tapctrl_shift_dr(TAPController *tap, bool tdi) @@ -338,7 +392,7 @@ static void tapctrl_shift_dr(TAPController *tap, bool tdi) static void tapctrl_update_dr(TAPController *tap) { - tapctrl_dump_register("Update DR", tap->dr, tap->dr_len); + tapctrl_dump_register("Update DR", tap->tdh->name, tap->dr, tap->dr_len); TAPDataHandler *tdh = tap->tdh; tdh->value = tap->dr; if (tdh->update) { @@ -377,7 +431,7 @@ static void tapctrl_step(TAPController *tap, bool tck, bool tms, bool tdi) tapctrl_reset(tap); break; case CAPTURE_DR: - tapctrl_capture_dr(tap, tap->ir_hold); + tapctrl_capture_dr(tap); break; case SHIFT_DR: tap->tdo = tap->dr & 0b1; @@ -408,12 +462,16 @@ static void tapctrl_bb_blink(TAPController *tap, bool light) {} static void tapctrl_bb_read(TAPController *tap) { - tap->outbuf[tap->outpos++] = '0' + (unsigned)tap->tdo; + (void)tap; } static void tapctrl_bb_quit(TAPController *tap) { - tapctrl_reset(tap); + (void)tap; + + qemu_log("%s: JTAG-requested termination\n", __func__); + + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); } static void tapctrl_bb_write(TAPController *tap, bool tck, bool tms, bool tdi) @@ -427,6 +485,9 @@ static void tapctrl_bb_reset(TAPController *tap, bool trst, bool srst) if (trst) { tapctrl_reset(tap); } + if (srst) { + tapctrl_system_reset(tap); + } tap->trst = trst; tap->srst = srst; } @@ -435,7 +496,7 @@ static void tapctrl_bb_reset(TAPController *tap, bool trst, bool srst) * TAP Server implementation */ -static void tap_read_byte(uint8_t ch) +static bool tap_read_byte(uint8_t ch) { switch ((char)ch) { case 'B': @@ -491,6 +552,9 @@ static void tap_read_byte(uint8_t ch) (unsigned)ch); break; } + + /* true if TDO level should be sent to the peer */ + return (int)ch == 'R'; } static int tap_chr_can_receive(void *opaque) @@ -504,12 +568,11 @@ static void tap_chr_receive(void *opaque, const uint8_t *buf, int size) TAPServerState *s = (TAPServerState *)opaque; for (unsigned ix = 0; ix < size; ix++) { - tap_read_byte(buf[ix]); - } - - if (s->tap->outpos) { - qemu_chr_fe_write_all(&s->chr, s->tap->outbuf, (int)s->tap->outpos); - s->tap->outpos = 0u; + if (tap_read_byte(buf[ix])) { + const TAPController *tap = s->tap; + uint8_t outbuf[1] = { '0' + (unsigned)tap->tdo }; + qemu_chr_fe_write_all(&s->chr, outbuf, (int)sizeof(outbuf)); + } } } diff --git a/jtag/trace-events b/jtag/trace-events index 9c7642df0473..555ad47348f6 100644 --- a/jtag/trace-events +++ b/jtag/trace-events @@ -1,8 +1,12 @@ -# JTAG -jtag_tapctrl_register(unsigned code, const char *name) "register %u: %s" -jtag_tapctrl_reset(bool tap, bool sys) "tap: %u, system: %u" -jtag_tapctrl_change_state(const char *prev, const char *new) "%s -> %s" +# jtag_bitbang.c + jtag_tapctrl_change(const char *msg, const char *value) "%s %s" +jtag_tapctrl_change_state(const char *prev, const char *new) "%s -> %s" +jtag_tapctrl_dump_register(const char *msg, uint64_t val, size_t len, const char *buf) "%s: 0x%" PRIx64 "/%zu [b%s]" +jtag_tapctrl_idump_register(const char *msg, const char *iname, uint64_t val, size_t len, const char *buf) "%s (%s): 0x%" PRIx64 "/%zu [b%s]" +jtag_tapctrl_init(size_t irlen, uint32_t ircode) "irlength %zu, idcode 0x%08x" +jtag_tapctrl_register(unsigned code, const char *name) "register 0x%x: %s" +jtag_tapctrl_reset(bool tap, bool sys) "tap: %u, system: %u" +jtag_tapctrl_select_dr(const char *name, uint64_t value) "Select DR %s 0x%02" PRIx64 jtag_tapctrl_step(bool tck, bool tms, bool tdi) "tck:%u tms:%u tdi:%u" -jtag_tapctr_dump_register(const char *msg, uint64_t val, size_t len, const char *buf) "%s: 0x%016" PRIx64 "/%zu [%s]" -jtag_tapctr_select_dr(const char *name, uint64_t value) "Select DR %s 0x%02" PRIx64 +jtag_tapctrl_system_reset(void) "SYSTEM RESET" diff --git a/scripts/jtag/.flake8 b/scripts/jtag/.flake8 new file mode 100644 index 000000000000..15fc7e33eb08 --- /dev/null +++ b/scripts/jtag/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 80 diff --git a/scripts/jtag/.pylintrc b/scripts/jtag/.pylintrc new file mode 100644 index 000000000000..3dcc728c9599 --- /dev/null +++ b/scripts/jtag/.pylintrc @@ -0,0 +1,7 @@ +[MESSAGES CONTROL] + + disable = too - few - public - methods, + too - many - arguments, too - many - branches, + too - many - instance - attributes, too - many - lines, too - many - locals, + too - many - nested - blocks, too - many - public - methods, + too - many - statements, unspecified - encoding diff --git a/scripts/jtag/__init__.py b/scripts/jtag/__init__.py new file mode 100644 index 000000000000..fe3d00da1f20 --- /dev/null +++ b/scripts/jtag/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""JTAG tools.""" diff --git a/scripts/jtag/bitbang.py b/scripts/jtag/bitbang.py new file mode 100644 index 000000000000..1c13f03b3f63 --- /dev/null +++ b/scripts/jtag/bitbang.py @@ -0,0 +1,180 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""JTAG controller for OpenOCD/QEMU bitbang protocol. + + :author: Emmanuel Blot + + Protocol abstract: + + TCLK TMS TDI + b'0' - Write 0 0 0 + b'1' - Write 0 0 1 + b'2' - Write 0 1 0 + b'3' - Write 0 1 1 + b'4' - Write 1 0 0 + b'5' - Write 1 0 1 + b'6' - Write 1 1 0 + b'7' - Write 1 1 1 + + TRST SRST + b'r' - Reset 0 0 + b's' - Reset 0 1 + b't' - Reset 1 0 + b'u' - Reset 1 1 + + b'R' - Read request -> b'0' or b'1' + b'Q' - Quit request +""" + +from logging import getLogger +from socket import socket +from time import time as now +from typing import Optional + +from .bits import BitSequence +from .jtag import JtagController + + +class JtagBitbangController(JtagController): + """JTAG master for Remote Bitbang connection.""" + + DEFAULT_PORT = 3335 + """Default TCP port.""" + + INSTRUCTIONS = dict(bypass=0x0, idcode=0x1) + """Common instruction register codes.""" + + RECV_TIMEOUT = 0.25 + """Maximum allowed time in seconds to receive a response from the JTAG + controller. + """ + + READ = 'R'.encode() + """JTAG bitbang code to receive data from TDO.""" + + QUIT = 'Q'.encode() + """JTAG bitbang code to quit.""" + + def __init__(self, sock: socket): + self._log = getLogger('jtag.ctrl') + self._sock = sock + self._last: Optional[bool] = None # Last deferred TDO bit + self._outbuf = bytearray() + self._tck = False + self._tms = False + self._tdi = False + self._trst = False + self._srst = False + + def tap_reset(self, use_trst: bool = False) -> None: + self._log.info('TAP reset (%s)', 'TRST' if use_trst else 'SW') + if use_trst: + self._trst = not self._trst + self._write(self._reset_code(self._trst, self._srst)) + self._trst = not self._trst + self._write(self._reset_code(self._trst, self._srst)) + else: + self.write_tms(BitSequence('11111')) + + def system_reset(self) -> None: + self._log.info('System reset') + self._write(self._reset_code(self._trst, self._srst)) + self._srst = not self._srst + self._write(self._reset_code(self._trst, self._srst)) + self._srst = not self._srst + self._write(self._reset_code(self._trst, self._srst)) + + def quit(self) -> None: + self._log.info('Quit') + self._sock.send(self.QUIT) + + def write_tms(self, modesel: BitSequence) -> None: + if not isinstance(modesel, BitSequence): + raise ValueError('Expect a BitSequence') + # apply the last TDO bit + if self._last is not None: + self._tdi = self._last + self._last = None + self._log.debug('write TMS [%d] %s', len(modesel), modesel) + while modesel: + tms = modesel.pop_left_bit() + self._write(self._bus_code(self._tck, tms, self._tdi)) + self._tck = not self._tck + self._write(self._bus_code(self._tck, tms, self._tdi)) + self._tck = not self._tck + self._tms = tms + + def write(self, out: BitSequence, use_last: bool = True): + if not isinstance(out, BitSequence): + raise ValueError('out is not a BitSequence') + if use_last: + if self._last is not None: + # TODO: check if this case needs to be handled + raise NotImplementedError('Last is lost') + self._last = out.pop_left_bit() + self._log.debug('write TDI [%d] %s', len(out), out) + while out: + tdi = out.pop_right_bit() + self._write(self._bus_code(self._tck, self._tms, tdi)) + self._tck = not self._tck + self._write(self._bus_code(self._tck, self._tms, tdi)) + self._tck = not self._tck + self._tdi = tdi + + def read(self, length: int) -> BitSequence: + if length == 0: + raise ValueError() + bseq = BitSequence() + rem = length + timeout = now() + self.RECV_TIMEOUT + self._log.debug('read %d bits, TMS: %d', length, self._tms) + for _ in range(length): + self._write(self._bus_code(self._tck, self._tms, self._tdi)) + self._tck = not self._tck + self._write(self._bus_code(self._tck, self._tms, self._tdi)) + self._tck = not self._tck + self._sock.send(self.READ) + while rem: + try: + data = self._sock.recv(length) + except TimeoutError: + if now() < timeout: + continue + raise + rem -= len(data) + bseq.push_right(data) + timeout = now() + self.RECV_TIMEOUT + bseq.reverse() + self._log.debug('read TDI [%d] %s', len(bseq), bseq) + return bseq + + @property + def tdi(self) -> bool: + return self._tdi + + @tdi.setter + def tdi(self, value: bool): + self._tdi = bool(value) + self._log.info('SET TDI %u', self._tdi) + + @property + def tms(self) -> bool: + return self._tms + + @tms.setter + def tms(self, value: bool): + self._tms = bool(value) + + @classmethod + def _bus_code(cls, tclk: bool, tms: bool, tdi: bool) -> int: + return 0x30 + ((int(tclk) << 2) | (int(tms) << 1) | tdi) + + @classmethod + def _reset_code(cls, trst: bool, srst: bool) -> int: + return ord('r') + ((int(trst) << 1) | srst) + + def _write(self, code: int): + self._log.debug('_write 0x%02x %s (%s)', code, f'{code-0x30:03b}', + chr(code)) + self._sock.send(bytes([code])) diff --git a/scripts/jtag/bits.py b/scripts/jtag/bits.py new file mode 100644 index 000000000000..873a12ab04b0 --- /dev/null +++ b/scripts/jtag/bits.py @@ -0,0 +1,592 @@ +# Copyright (c) 2010-2024 Emmanuel Blot +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Bit sequence helpers for JTAG/DTM. + + BitSequence is a wrapper to help manipulating bits with the JTAG tools. + + >>> empty = BitSequence() + + >>> len(empty) + 0 + >>> int(empty) + 0 + >>> bool(empty) + False + >>> bs = BitSequence(0xC4, 8) + + >>> bs + [1, 1, 0, 0, 0, 1, 0, 0] + >>> str(bs) + '11000100' + >>> bs = BitSequence('11000100') + + >>> bs + [1, 1, 0, 0, 0, 1, 0, 0] + >>> int(bs) + 196 + >>> bs = BitSequence(b'11000100') + + >>> bs + [1, 1, 0, 0, 0, 1, 0, 0] + >>> bs = BitSequence([1, 1, 0, 0, 0, 1, 0, 0]) + + >>> bs + [1, 1, 0, 0, 0, 1, 0, 0] + >>> bs.pop_right() + [0] + >>> bs.pop_right(2) + [1, 0] + >>> bs.pop_right_bit() + False + >>> bs.push_right('0111') + [1, 1, 0, 0, 0, 1, 1, 1] + >>> bs.pop_left_bit() + True + >>> bs.pop_left(2) + [1, 0] + >>> bs + [0, 0, 1, 1, 1] + >>> len(bs) + 5 + >>> bs.push_left([False, True, True]) + [0, 1, 1, 0, 0, 1, 1, 1] + >>> bs.rll() + [1, 1, 0, 0, 1, 1, 1, 0] + >>> bs.rrl(3) + [1, 1, 0, 1, 1, 0, 0, 1] + >>> bs.inc() + [1, 1, 0, 1, 1, 0, 1, 0] + >>> bs.invert() + [0, 0, 1, 0, 0, 1, 0, 1] + >>> bs.reverse() + [1, 0, 1, 0, 0, 1, 0, 0] + >>> bs = BitSequence(0xff, 8) + >>> bs.inc() + [0, 0, 0, 0, 0, 0, 0, 0] + >>> bs.invariant() + False + >>> len(bs) + 8 + >>> bs.dec() + [1, 1, 1, 1, 1, 1, 1, 1] + >>> bs.invariant() + True + >>> len(bs) + 8 + >>> bs1 = BitSequence(0x13, 5) # 10011 + + >>> bs2 = BitSequence(0x19, 5) # 11001 + + >>> bs3 = bs2.copy().reverse() + + >>> bs1 == bs3 + True + >>> bs1 == bs2 + False + >>> bs1 != bs2 + True + >>> bs1 < bs2 + True + >>> bs1 <= bs2 + True + >>> bs1 > bs2 + False + >>> bs1 | bs2 + [1, 1, 0, 1, 1] + >>> bs1 & bs2 + [1, 0, 0, 0, 1] + >>> bs1 ^ bs2 + [0, 1, 0, 1, 0] + >>> ~(bs1 ^ bs2) + [1, 0, 1, 0, 1] +""" + +from typing import Any, Iterable, List, Union + + +class BitSequenceError(Exception): + """Bit sequence error""" + + +BitSequenceInitializer = Union['BitSequence', str, int, bytes, bytearray, + Iterable[int], Iterable[bool], None] +"""Supported types to initialize a BitSequence.""" + + +class BitSequence: + """Bit sequence. + + Support most of the common bit operations and conversion from and to + integral values, as well as sequence of boolean, int and characters. + + Bit sequence objects are iterable. + + :param value: initial value + :param length: count of signficant bits in the bit sequence + """ + + # pylint: disable=protected-access + + def __init__(self, value: BitSequenceInitializer = None, + width: int = 0): + if value is None: + self._int = 0 + self._width = width + return + if isinstance(value, BitSequence): + self._int, self._width = value._int, value._width + return + if isinstance(value, int): + bseq = self.from_int(value, width) + self._int, self._width = bseq._int, bseq._width + return + if is_iterable(value): + bseq = self.from_iterable(value) + if width and width != bseq._width: + raise ValueError('Specified width does not match input value') + self._int, self._width = bseq._int, bseq._width + return + raise BitSequenceError(f'Cannot initialize from a {type(value)}') + + @classmethod + def from_iterable(cls, iterable: Iterable) -> 'BitSequence': + """Instanciate a BitSequence from an iterable.""" + # pylint: disable=duplicate-key + smap = { + 0: 0, 1: 1, # as int + '0': 0, '1': 1, # as string + 0x30: 0, 0x31: 1, # as bytes + False: 0, True: 1, # as bool + } + value = 0 + width = 0 + for bit in iterable: + try: + value <<= 1 + value |= smap[bit] + width += 1 + except KeyError as exc: + raise ValueError(f"Invalid item '{bit}' in iterable at pos " + f"{width}") from exc + return BitSequence.from_int(value, width) + + @classmethod + def from_int(cls, value: int, width: int) -> 'BitSequence': + """Instanciate a BitSequence from an integer value.""" + bseq = BitSequence() + bseq._int = value + bseq._width = width + return bseq + + def __len__(self): + return self._width + + def __bool__(self): + # report wether the Bit Sequence is empty or not. + # to fold a single bit sequence into a boolean, see #to_bit + return bool(self._width) + + def __int__(self): + return self._int + + def __repr__(self) -> str: + sseq = ', '.join((f'{b:0d}' for b in self)) + return f'[{sseq}]' + + def __str__(self) -> str: + return f'{self._int:0{self._width}b}' + + def copy(self) -> 'BitSequence': + """Duplicate bitsequence.""" + bseq = self.__class__() + bseq._int = self._int + bseq._width = self._width + return bseq + + @property + def mask(self) -> int: + """Bit mask.""" + return (1 << self._width) - 1 + + def to_bit(self) -> bool: + """Fold the sequence into a single bit, if possible""" + if self._width != 1: + raise BitSequenceError("BitSequence too large") + return bool(self._int & 1) + + def to_byte(self, msb: bool = False) -> int: + """Convert the sequence into a single byte value, if possible""" + if self._width > 8: + raise BitSequenceError("Cannot fit into a single byte") + if not msb: + bseq = BitSequence(self) + bseq.reverse() + else: + bseq = self + return self._int + + def to_bytes(self) -> bytes: + """Return the internal representation as bytes""" + return bytes((int(b) for b in self)) + + def to_bool_list(self) -> List[bool]: + """Convert the sequence into a list of boolean values.""" + return list(self) + + def to_bytestream(self, msb: bool = False, msby: bool = False) -> bytes: + """Convert the sequence into a sequence of byte values""" + out: List[int] = [] + bseq = BitSequence(self) + if not msb: + bseq.reverse() + while bseq._width: + out.append(self._int & 0xff) + self._int >>= 8 + if msby and not msb: + out.reverse() + return bytes(out) + + def reverse(self) -> 'BitSequence': + """In-place reverse. + + :return: self + """ + bseq = self.__class__.from_iterable(reversed(self)) + assert bseq._width == self._width + self._int = bseq._int + return self + + def invert(self) -> 'BitSequence': + """In-place invert of each sequence value. + + :return: self + """ + self._int = ~self._int & self.mask + return self + + def push_right(self, bseq: BitSequenceInitializer) -> 'BitSequence': + """Push a bit sequence to the right side. + + :param bseq: the bit sequence to push + :return: self + """ + if not isinstance(bseq, BitSequence): + bseq = BitSequence(bseq) + self._int <<= len(bseq) + self._int |= bseq._int + self._width += len(bseq) + return self + + def push_left(self, bseq: BitSequenceInitializer) -> 'BitSequence': + """Push a bit sequence to the left side. + + :param bseq: the bit sequence to push + :return: self + """ + if not isinstance(bseq, BitSequence): + bseq = BitSequence(bseq) + self._int = (bseq._int << self._width) | self._int + self._width += len(bseq) + return self + + def pop_right(self, count: int = 1) -> 'BitSequence': + """Pop bits from the right side. + + :param count: how many bits to pop + :return: popped bits a a new BitSequence + """ + if count > self._width: + raise ValueError('Count too large') + if count == 0: + return BitSequence() + if count < 0: + raise ValueError('Negative shift is not defined') + bseq = self.__class__.from_int(self._int & ((1 << count) - 1), count) + self._int >>= count + self._width -= count + return bseq + + def pop_left(self, count: int = 1) -> 'BitSequence': + """Pop bits from the left side. + + :param count: how many bits to pop + :return: popped bits a a new BitSequence + """ + if count > self._width: + raise ValueError('Count too large') + if count == 0: + return BitSequence() + if count < 0: + raise ValueError('Negative shift is not defined') + shift = self._width - count + bseq = self.__class__.from_int(self._int >> shift, count) + self._int &= (1 << shift) - 1 + self._width -= count + return bseq + + def pop_right_bit(self) -> bool: + """Pop a single bit from the right side. + + :return: popped bit + """ + if self._width == 0: + raise RuntimeError('Empty bit sequence') + bit = bool(self._int & 1) + self._int >>= 1 + self._width -= 1 + return bit + + def pop_left_bit(self) -> bool: + """Pop a single bit from the left side. + + :return: popped bit + """ + if self._width == 0: + raise RuntimeError('Empty bit sequence') + bit = bool(self._int >> (self._width - 1)) + self._width -= 1 + self._int &= self.mask + return bit + + def rll(self, count: int = 1) -> 'BitSequence': + """Rotate Left Logical. + + :return: self + """ + count %= self._width + bseq = self.pop_left(count) + self.push_right(bseq) + return self + + def rrl(self, count: int = 1) -> 'BitSequence': + """Rotate Right Logical. + + :return: self + """ + count %= self._width + bseq = self.pop_right(count) + self.push_left(bseq) + return self + + def inc(self, wrap: bool = True) -> 'BitSequence': + """Increment the sequence.""" + self._int += 1 + if not wrap: + if self._int >> self._width: + self._width += 1 + else: + self._int &= self.mask + return self + + def dec(self, wrap: bool = True) -> 'BitSequence': + """Decrement the sequence""" + self._int -= 1 + if not wrap: + if not self._int >> self._width: + self._width -= 1 + else: + self._int &= self.mask + return self + + def invariant(self) -> bool: + """Tells whether all bits of the sequence are of the same value. + + Return the value, or ValueError if the bits are not of the same + value + """ + if self._int == 0: + return False + if self._int == self.mask: + return True + raise ValueError('Bits do no match') + + class Iterator: + """BitSequence iterator. + + Iterate from left to right (MSB to LSB) if reverse is not set. + + :param bseq: the BitSequence to iterate + :param reverse: whether to create a reverse iterator + """ + + def __init__(self, bseq: 'BitSequence', reverse: bool = False): + self._bseq = bseq + self._reverse = reverse + self._width = bseq._width + self._pos = 0 + + def __iter__(self) -> 'BitSequence.Iterator': + return self + + def __next__(self) -> bool: + if self._width != self._bseq._width: + raise RuntimeError('BitSequence modified while iterating') + if self._pos >= self._bseq._width: + raise StopIteration() + if self._reverse: + bit = bool((self._bseq._int >> self._pos) & 1) + else: + pos = self._width - self._pos - 1 + bit = bool((self._bseq._int >> pos) & 1) + self._pos += 1 + return bit + + def __iter__(self) -> 'BitSequence.Iterator': + """Iterate from left to right, i.e. MSB to LSB.""" + return self.__class__.Iterator(self) + + def __reversed__(self): + """Iterate from right to left, i.e. LSB to MSB.""" + return self.__class__.Iterator(self, reverse=True) + + def __eq__(self, other: 'BitSequence') -> bool: + if not isinstance(other, self.__class__): + raise ValueError(f'Cannot compare with {type(other)}') + return self._cmp(other) == 0 + + def __ne__(self, other: 'BitSequence') -> bool: + if not isinstance(other, self.__class__): + raise ValueError(f'Cannot compare with {type(other)}') + return not self == other + + def __le__(self, other: 'BitSequence') -> bool: + if not isinstance(other, self.__class__): + raise ValueError(f'Cannot compare with {type(other)}') + return self._cmp(other) <= 0 + + def __lt__(self, other: 'BitSequence') -> bool: + if not isinstance(other, self.__class__): + raise ValueError(f'Cannot compare with {type(other)}') + return self._cmp(other) < 0 + + def __ge__(self, other: 'BitSequence') -> bool: + if not isinstance(other, self.__class__): + raise ValueError(f'Cannot compare with {type(other)}') + return self._cmp(other) >= 0 + + def __gt__(self, other: 'BitSequence') -> bool: + if not isinstance(other, self.__class__): + raise ValueError(f'Cannot compare with {type(other)}') + return self._cmp(other) > 0 + + def _cmp(self, other: 'BitSequence') -> int: + # the bit sequence should be of the same length + ld = self._width - other._width + if ld: + return ld + return self._int - other._int + + def __and__(self, other: 'BitSequence') -> 'BitSequence': + if not isinstance(other, self.__class__): + raise ValueError('Need a BitSequence to combine') + if self._width != other._width: + raise ValueError('Sequences must be the same size') + value = self._int & other._int + return self.__class__.from_int(value, self._width) + + def __or__(self, other: 'BitSequence') -> 'BitSequence': + if not isinstance(other, self.__class__): + raise ValueError('Need a BitSequence to combine') + if self._width != other._width: + raise ValueError('Sequences must be the same size') + value = self._int | other._int + return self.__class__.from_int(value, self._width) + + def __xor__(self, other: 'BitSequence') -> 'BitSequence': + if not isinstance(other, self.__class__): + raise ValueError('Need a BitSequence to combine') + if self._width != other._width: + raise ValueError('Sequences must be the same size') + value = self._int ^ other._int + return self.__class__.from_int(value, self._width) + + def __invert__(self) -> 'BitSequence': + value = (~self._int) & self.mask + return self.__class__.from_int(value, self._width) + + def __ilshift__(self, count) -> 'BitSequence': + self.pop_left() + return self + + def __irshift__(self, count) -> 'BitSequence': + self.pop_right() + return self + + def __getitem__(self, index) -> 'BitSequence': + # TODO: not yet validated, likely buggy + if isinstance(index, slice): + bits: List[int] = [] + for bpos in range(index.start, index.stop, index.step): + if bpos < 0: + continue + if bpos >= self._width: + break + bits.append((self._int >> bpos) & 1) + return self.__class__.from_iterable(reversed(bits)) + if not isinstance(index, int): + raise TypeError(f'{self.__class__.__name__} indices must be ' + f'integers or slices, not {type(index)}') + if ~index >= self._width: + raise IndexError(f'{self.__class__.__name__} index out of range') + if index >= 0: + value = (self._int >> index) & 1 + else: + value = (self._int >> (self._width - index - 1)) & 1 + return self.__class__.from_int(value, 1) + + def __setitem__(self, index, value) -> None: + # TODO: not yet validated, likely buggy + if isinstance(index, slice): + if not isinstance(value, BitSequence): + if not is_iterable(value): + raise TypeError(f'Cannot set item with {type(value)}') + value = self.from_iterable(value) + else: + value = value.copy() + for bpos in range(index.start, index.stop, index.step): + if bpos < 0: + continue + if bpos >= self._width: + break + self._int &= ~(1 << bpos) + self._int |= int(value.pop_right()) << bpos + if value._width == 0: + break + if not isinstance(index, int): + raise TypeError(f'{self.__class__.__name__} indices must be ' + f'integers or slices, not {type(index)}') + if isinstance(value, BitSequence): + value = value.tobit() + elif isinstance(value, int): + if value not in (0, 1): + raise ValueError('Invalid value') + value = int(value) + if ~index >= self._width: + raise IndexError(f'{self.__class__.__name__} index out of ' + f'range') + if index < 0: + index = self._width - index - 1 + self._int[index] = value + + +def is_iterable(obj: Any) -> bool: + """Tells whether an instance is iterable or not. + + :param obj: the instance to test + :type obj: object + :return: True if the object is iterable + :rtype: bool + """ + try: + iter(obj) + return True + except TypeError: + return False + + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/scripts/jtag/jtag.py b/scripts/jtag/jtag.py new file mode 100644 index 000000000000..92b7dfe6635c --- /dev/null +++ b/scripts/jtag/jtag.py @@ -0,0 +1,351 @@ +# Copyright (c) 2010-2024, Emmanuel Blot +# Copyright (c) 2016, Emmanuel Bouaziz +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""JTAG tools. + + Based on JTAG support for FTDI from PyFtdi module +""" + +# pylint: enable=missing-function-docstring + +from logging import getLogger +from typing import List, Optional, Tuple, Union + +from .bits import BitSequence + + +class JtagError(Exception): + """Generic JTAG error.""" + + +class JtagState: + """Test Access Port controller state. + + :param name: the name of the state + :param modes: categories to which the state belongs + """ + + def __init__(self, name: str, modes: Tuple[str, str]): + self.name = name + self.modes = modes + self.exits = [self, self] # dummy value before initial configuration + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def setx(self, fstate: 'JtagState', tstate: 'JtagState'): + """Define the two exit state of a state.""" + self.exits = [fstate, tstate] + + def getx(self, event) -> 'JtagState': + """Retrieve the exit state of the state. + + :param event: evaluated as a boolean value + :return: next state + """ + return self.exits[int(bool(event))] + + def is_of(self, mode: str) -> bool: + """Report if the state is a member of the specified mode.""" + return mode in self.modes + + +class JtagStateMachine: + """Test Access Port controller state machine.""" + + def __init__(self): + self._log = getLogger('jtag.fsm') + self.states = {} + for state, modes in [('test_logic_reset', ('reset', ' idle')), + ('run_test_idle', ('idle',)), + ('select_dr_scan', ('dr',)), + ('capture_dr', ('dr', 'shift', 'capture')), + ('shift_dr', ('dr', 'shift')), + ('exit_1_dr', ('dr', 'update', 'pause')), + ('pause_dr', ('dr', 'pause')), + ('exit_2_dr', ('dr', 'shift', 'udpate')), + ('update_dr', ('dr', 'idle')), + ('select_ir_scan', ('ir',)), + ('capture_ir', ('ir', 'shift', 'capture')), + ('shift_ir', ('ir', 'shift')), + ('exit_1_ir', ('ir', 'udpate', 'pause')), + ('pause_ir', ('ir', 'pause')), + ('exit_2_ir', ('ir', 'shift', 'update')), + ('update_ir', ('ir', 'idle'))]: + self.states[state] = JtagState(state, modes) + self['test_logic_reset'].setx(self['run_test_idle'], + self['test_logic_reset']) + self['run_test_idle'].setx(self['run_test_idle'], + self['select_dr_scan']) + self['select_dr_scan'].setx(self['capture_dr'], + self['select_ir_scan']) + self['capture_dr'].setx(self['shift_dr'], self['exit_1_dr']) + self['shift_dr'].setx(self['shift_dr'], self['exit_1_dr']) + self['exit_1_dr'].setx(self['pause_dr'], self['update_dr']) + self['pause_dr'].setx(self['pause_dr'], self['exit_2_dr']) + self['exit_2_dr'].setx(self['shift_dr'], self['update_dr']) + self['update_dr'].setx(self['run_test_idle'], + self['select_dr_scan']) + self['select_ir_scan'].setx(self['capture_ir'], + self['test_logic_reset']) + self['capture_ir'].setx(self['shift_ir'], self['exit_1_ir']) + self['shift_ir'].setx(self['shift_ir'], self['exit_1_ir']) + self['exit_1_ir'].setx(self['pause_ir'], self['update_ir']) + self['pause_ir'].setx(self['pause_ir'], self['exit_2_ir']) + self['exit_2_ir'].setx(self['shift_ir'], self['update_ir']) + self['update_ir'].setx(self['run_test_idle'], self['select_dr_scan']) + self._current = self['test_logic_reset'] + + def __getitem__(self, name: str) -> JtagState: + return self.states[name] + + @property + def state(self) -> JtagState: + """Return the current state.""" + return self._current + + def state_of(self, mode: str) -> bool: + """Report if the current state is of the specified mode.""" + return self._current.is_of(mode) + + def reset(self): + """Reset the state machine.""" + self._current = self['test_logic_reset'] + + def find_path(self, target: Union[JtagState, str], + source: Union[JtagState, str, None] = None) \ + -> List[JtagState]: + """Find the shortest event sequence to move from source state to + target state. If source state is not specified, used the current + state. + + :return: the list of states, including source and target states. + """ + if source is None: + source = self.state + if isinstance(source, str): + source = self[source] + if isinstance(target, str): + target = self[target] + + def next_path(state, target, path): + # this test match the target, path is valid + if state == target: + return path+[state] + # candidate paths + paths = [] + for xstate in state.exits: + # next state is self (loop around), kill the path + if xstate == state: + continue + # next state already in upstream (loop back), kill the path + if xstate in path: + continue + # try the current path + npath = next_path(xstate, target, path + [state]) + # downstream is a valid path, store it + if npath: + paths.append(npath) + # keep the shortest path + return min(((len(path), path) for path in paths), + key=lambda x: x[0])[1] if paths else [] + return next_path(source, target, []) + + @classmethod + def get_events(cls, path): + """Build up an event sequence from a state sequence, so that the + resulting event sequence allows the JTAG state machine to advance + from the first state to the last one of the input sequence""" + events = [] + for sstate, dstate in zip(path[:-1], path[1:]): + for epos, xstate in enumerate(sstate.exits): + if xstate == dstate: + events.append(epos) + if len(events) != len(path) - 1: + raise JtagError("Invalid path") + return BitSequence(events) + + def handle_events(self, events: BitSequence) -> None: + """State machine stepping. + + :param events: a sequence of boolean events to advance the FSM. + """ + for event in events: + self._current = self._current.getx(event) + + +class JtagController: + """JTAG master API.""" + + INSTRUCTIONS = dict(bypass=0x0, idcode=0x1) + """Common instruction register codes.""" + + def tap_reset(self, use_trst: bool = False) -> None: + """Reset the TAP controller. + + :param use_trst: use TRST HW wire if available + """ + raise NotImplementedError('ABC') + + def system_reset(self) -> None: + """Reset the device.""" + + def quit(self) -> None: + """Terminate session.""" + + def write_tms(self, modesel: BitSequence) -> None: + """Change the TAP controller state. + + :note: modesel content may be consumed, i.e. emptied + :note: last TMS bit should be stored and clocked on next write + request + + :param modesel: the bit sequence of TMS bits to clock in + """ + raise NotImplementedError('ABC') + + def write(self, out: BitSequence, use_last: bool = True): + """Write a sequence of bits to TDI. + + :note: out content may be consumed, i.e. emptied + :param out: the bot sequence of TDI bits to clock in + :param use_last: whether to clock in the stored TMS bits on first + clock cycle + """ + raise NotImplementedError('ABC') + + def read(self, length: int) -> BitSequence: + """Read out a sequence of bits from TDO. + + :param length: the number of bits to clock out from the remote device + :return: the received TDO bits (length-long) + """ + raise NotImplementedError('ABC') + + @property + def tdi(self) -> bool: + """Get current TDI value.""" + raise NotImplementedError('ABC') + + @tdi.setter + def tdi(self, value: bool): + """Set TDI value, to be clocked out on next operation.""" + raise NotImplementedError('ABC') + + @property + def tms(self) -> bool: + """Get current TMS value.""" + raise NotImplementedError('ABC') + + @tms.setter + def tms(self, value: bool): + """Set TMS value, to be clocked out on next operation.""" + raise NotImplementedError('ABC') + + +class JtagEngine: + """High-level JTAG engine controller""" + + def __init__(self, ctrl: 'JtagController'): + self._ctrl = ctrl + self._log = getLogger('jtag.eng') + self._fsm = JtagStateMachine() + self._seq = bytearray() + + @property + def fsm(self) -> JtagStateMachine: + """Return the state machine.""" + return self._fsm + + @property + def controller(self) -> 'JtagController': + """Return the JTAG controller.""" + return self._ctrl + + def reset(self) -> None: + """Reset the attached TAP controller""" + self._ctrl.reset() + self._fsm.reset() + + def get_available_statenames(self): + """Return a list of supported state name""" + return [str(s) for s in self._fsm.states] + + def change_state(self, statename) -> None: + """Advance the TAP controller to the defined state""" + # find the state machine path to move to the new instruction + path = self._fsm.find_path(statename) + self._log.debug('path: %s', + ', '.join((str(s).upper() for s in path[1:]))) + # convert the path into an event sequence + events = self._fsm.get_events(path) + # update the remote device tap controller (write TMS consumes the seq) + self._ctrl.write_tms(events.copy()) + # update the current state machine's state + self._fsm.handle_events(events) + + def go_idle(self) -> None: + """Change the current TAP controller to the IDLE state""" + self.change_state('run_test_idle') + + def run(self) -> None: + """Change the current TAP controller to the IDLE state""" + self.change_state('run_test_idle') + + def capture_ir(self) -> None: + """Capture the current instruction from the TAP controller""" + self.change_state('capture_ir') + + def write_ir(self, instruction) -> None: + """Change the current instruction of the TAP controller""" + self.change_state('shift_ir') + ilength = len(instruction) # write consumes the instruction + self._ctrl.write(instruction) + self.change_state('update_ir') + # flush IR output + self._ctrl.tms = False + self._ctrl.read(ilength) + + def capture_dr(self) -> None: + """Capture the current data register from the TAP controller""" + self.change_state('capture_dr') + + def write_dr(self, data) -> None: + """Change the data register of the TAP controller""" + self.change_state('shift_dr') + self._ctrl.write(data) + self.change_state('update_dr') + + def read_dr(self, length: int) -> BitSequence: + """Read the data register from the TAP controller""" + self.change_state('shift_dr') + self._ctrl.tms = False + data = self._ctrl.read(length) + self.change_state('update_dr') + return data + + def write_tms(self, out) -> None: + """Change the TAP controller state""" + self._ctrl.write_tms(out) + + def write(self, out, use_last=False) -> None: + """Write a sequence of bits to TDI""" + self._ctrl.write(out, use_last) + + def read(self, length): + """Read out a sequence of bits from TDO""" + return self._ctrl.read(length) + + def set_tdi(self, value: bool): + """Force default TDI value, clocked out on each cycle.""" + self._ctrl.tdi = value + + def set_tms(self, value: bool): + """Force default TMS value clocked out on each cycle.""" + self._ctrl.tms = value diff --git a/scripts/opentitan/clang-format.d/jtag.lst b/scripts/opentitan/clang-format.d/jtag.lst new file mode 100644 index 000000000000..754467c64adb --- /dev/null +++ b/scripts/opentitan/clang-format.d/jtag.lst @@ -0,0 +1,2 @@ +jtag/*.c +include/exec/jtagstub.h diff --git a/.gitlab-ci.d/opentitan/ot.clang_format b/scripts/opentitan/clang-format.d/opentitan.lst similarity index 100% rename from .gitlab-ci.d/opentitan/ot.clang_format rename to scripts/opentitan/clang-format.d/opentitan.lst diff --git a/scripts/opentitan/clang-tidy.d/jtag.lst b/scripts/opentitan/clang-tidy.d/jtag.lst new file mode 100644 index 000000000000..411d4c986363 --- /dev/null +++ b/scripts/opentitan/clang-tidy.d/jtag.lst @@ -0,0 +1 @@ +jtag/*.c diff --git a/.gitlab-ci.d/opentitan/ot.clang_tidy b/scripts/opentitan/clang-tidy.d/opentitan.lst similarity index 100% rename from .gitlab-ci.d/opentitan/ot.clang_tidy rename to scripts/opentitan/clang-tidy.d/opentitan.lst diff --git a/scripts/opentitan/dtm.py b/scripts/opentitan/dtm.py new file mode 100755 index 000000000000..14c86900e583 --- /dev/null +++ b/scripts/opentitan/dtm.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2024, Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""Debug Transport Module tiny demo. + + :author: Emmanuel Blot +""" + +from argparse import ArgumentParser, Namespace +from os import linesep +from os.path import dirname, join as joinpath, normpath +from socket import create_connection +from traceback import format_exc +from typing import Optional +import sys + +# pylint: disable=wrong-import-position +# pylint: disable=wrong-import-order +# pylint: disable=import-error + +# JTAG module is available from the scripts/ directory +sys.path.append(joinpath(normpath(dirname(dirname(sys.argv[0]))))) + +from ot.util.log import configure_loggers # noqa: E402 +from ot.dtm import DebugTransportModule # noqa: E402 +from jtag.bits import BitSequence # noqa: E402 +from jtag.bitbang import JtagBitbangController # noqa: E402 +from jtag.jtag import JtagEngine # noqa: E402 + + +def idcode(engine: JtagEngine, ir_length: int) -> None: + """Retrieve ID code.""" + code = JtagBitbangController.INSTRUCTIONS['idcode'] + engine.write_ir(BitSequence(code, ir_length)) + value = engine.read_dr(32) + engine.go_idle() + return int(value) + + +def main(): + """Entry point.""" + debug = True + try: + args: Optional[Namespace] = None + argparser = ArgumentParser(description=sys.modules[__name__].__doc__) + qvm = argparser.add_argument_group(title='Virtual machine') + + qvm.add_argument('-H', '--host', default='127.0.0.1', + help='JTAG host (default: localhost)') + qvm.add_argument('-P', '--port', type=int, + default=JtagBitbangController.DEFAULT_PORT, + help=f'JTAG port, ' + f'default: {JtagBitbangController.DEFAULT_PORT}') + qvm.add_argument('-I', '--info', action='store_true', + help='Report JTAG ID code and DTM configuration') + qvm.add_argument('-l', '--ir-length', type=int, default=5, + help='bit length of the IR register') + extra = argparser.add_argument_group(title='Extras') + extra.add_argument('-v', '--verbose', action='count', + help='increase verbosity') + extra.add_argument('-d', '--debug', action='store_true', + help='enable debug mode') + + args = argparser.parse_args() + debug = args.debug + + configure_loggers(args.verbose, 'dtm', 'jtag') + + sock = create_connection((args.host, args.port), timeout=0.5) + sock.settimeout(0.1) + ctrl = JtagBitbangController(sock) + eng = JtagEngine(ctrl) + ctrl.tap_reset(True) + ir_length = args.ir_length + dtm = DebugTransportModule(eng, ir_length) + if args.info: + code = idcode(eng, ir_length) + print(f'IDCODE: 0x{code:x}') + sys.exit(0) + version = dtm['dtmcs'].dmi_version + abits = dtm['dtmcs'].abits + print(f'DTM: v{version[0]}.{version[1]}, {abits} bits') + dtm['dtmcs'].check() + dtm['dtmcs'].dmireset() + + # pylint: disable=broad-except + except Exception as exc: + print(f'{linesep}Error: {exc}', file=sys.stderr) + if debug: + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) + except KeyboardInterrupt: + sys.exit(2) + + +if __name__ == '__main__': + main() diff --git a/scripts/opentitan/flashgen.py b/scripts/opentitan/flashgen.py index dcd6308933d6..ad62590d0562 100755 --- a/scripts/opentitan/flashgen.py +++ b/scripts/opentitan/flashgen.py @@ -1,17 +1,19 @@ #!/usr/bin/env python3 -"""Create/update an OpenTitan backend flash file. -""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""Create/update an OpenTitan backend flash file. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser, FileType from binascii import hexlify from hashlib import sha256 from itertools import repeat from io import BytesIO -from logging import DEBUG, ERROR, getLogger, Formatter, StreamHandler +from logging import getLogger from os import SEEK_END, SEEK_SET, rename, stat from os.path import abspath, basename, exists, isfile from re import sub as re_sub @@ -21,6 +23,8 @@ from typing import (Any, BinaryIO, Dict, Iterator, List, NamedTuple, Optional, Tuple, Union) +from ot.util.log import configure_loggers + try: # note: pyelftools package is an OpenTitan toolchain requirement, see # python-requirements.txt file from OT top directory. @@ -826,15 +830,7 @@ def main(): args = argparser.parse_args() debug = args.debug - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = Formatter('%(levelname)8s [%(lineno)d] %(name)-12s ' - '%(message)s') - log = getLogger('flashgen') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + configure_loggers(args.verbose, 'flashgen') use_bl0 = bool(args.boot) or len(args.otdesc) > 1 gen = FlashGen(args.offset if use_bl0 else 0, bool(args.unsafe_elf), diff --git a/scripts/opentitan/gdbreplay.py b/scripts/opentitan/gdbreplay.py index a2e680c453db..3dfefa6814a1 100755 --- a/scripts/opentitan/gdbreplay.py +++ b/scripts/opentitan/gdbreplay.py @@ -1,27 +1,29 @@ #!/usr/bin/env python3 -"""QEMU GDB replay. -""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""QEMU GDB replay. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser, FileType, Namespace from binascii import hexlify from io import BytesIO -from logging import (Formatter, StreamHandler, CRITICAL, DEBUG, INFO, ERROR, - WARNING, getLogger) -from os import isatty, linesep +from logging import getLogger +from os import linesep from os.path import dirname, isfile, join as joinpath, normpath from re import compile as re_compile from socket import (SOL_SOCKET, SO_REUSEADDR, SHUT_RDWR, socket, timeout as LegacyTimeoutError) from string import ascii_uppercase -from sys import exit as sysexit, modules, stderr, stdout +from sys import exit as sysexit, modules, stderr from traceback import format_exc from typing import (BinaryIO, Dict, Iterator, List, Optional, TextIO, Tuple, Union) +from ot.util.log import configure_loggers try: from elftools.common.exceptions import ELFError @@ -33,40 +35,6 @@ Segment = None -class CustomFormatter(Formatter): - """Custom log formatter for ANSI terminals. Colorize log levels. - """ - - GREY = "\x1b[38;20m" - YELLOW = "\x1b[33;1m" - RED = "\x1b[31;1m" - MAGENTA = "\x1b[35;1m" - WHITE = "\x1b[37;1m" - RESET = "\x1b[0m" - FORMAT_LEVEL = '%(levelname)8s' - FORMAT_TRAIL = ' %(name)-10s %(message)s' - - COLOR_FORMATS = { - DEBUG: f'{GREY}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - INFO: f'{WHITE}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - WARNING: f'{YELLOW}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - ERROR: f'{RED}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - CRITICAL: f'{MAGENTA}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - } - - PLAIN_FORMAT = f'{FORMAT_LEVEL}{FORMAT_TRAIL}' - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self._istty = isatty(stdout.fileno()) - - def format(self, record): - log_fmt = self.COLOR_FORMATS[record.levelno] if self._istty \ - else self.PLAIN_FORMAT - formatter = Formatter(log_fmt) - return formatter.format(record) - - class ElfBlob: """Load ELF application.""" @@ -463,7 +431,7 @@ class QEMUGDBReplay: # Trace 0: 0x280003d00 [00000000/00008c9a/00101003/ff020000] _boot_start TCRE = re_compile(r'^Trace\s(\d+):\s0x[0-9a-f]+\s\[[0-9a-f]+/([0-9a-f]+)' - r'/[0-9a-f]+/[0-9a-f]+\]\s(\w+)\s*$') + r'/[0-9a-f]+/[0-9a-f]+\](?:\s([&,<>\s\w:]+))?\s*$') """Regex to parse QEMU execution trace from a QEMU log file.""" SIGNALS = { @@ -495,21 +463,26 @@ def xlen(self) -> int: """ return self._xlen or 4 - def load(self, qfp: TextIO) -> None: + def load(self, qfp: TextIO, cpus: Optional[List[int]] = None) -> None: """Load a recorded execution stream from a QEMU log file. see QEMU `-d exec` option. :param qfp: text stream to parse """ + threshold = 10 for lno, line in enumerate(qfp, start=1): tmo = self.TCRE.match(line) if not tmo: continue scpu, spc, func = tmo.groups() + if lno > threshold: + threshold *= 10 + if not lno % threshold: + self._log.debug('Parsed %d lines', lno) xcpu = int(scpu) + if cpus and xcpu not in cpus: + continue xpc = int(spc, 16) - if not lno % 10000: - self._log.debug('Parsed %d lines', lno) if xcpu not in self._vcpus: self._vcpus[xcpu] = QEMUVCPU(self._memctrl) self._vcpus[xcpu].record(xpc, func) @@ -832,6 +805,8 @@ def main(): argparser.add_argument('-e', '--elf', action='append', type=FileType('rb'), help='ELF application') + argparser.add_argument('-c', '--cpu', action='append', type=int, + help='Only consider selected CPUs') argparser.add_argument('-a', '--address', action='append', type=lambda x: int(x, 16 if x[1:2].lower() == 'x' else 10), @@ -850,14 +825,7 @@ def main(): args = argparser.parse_args() debug = args.debug - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = CustomFormatter() - log = getLogger('gdbrp') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + configure_loggers(args.verbose, 'gdbrp') acount = len(args.address or []) bcount = len(args.bin or []) @@ -874,7 +842,7 @@ def main(): for addr, blob in zip(args.address, args.bin): gdbr.load_bin(addr, blob) if args.trace: - gdbr.load(args.trace) + gdbr.load(args.trace, args.cpu) gdbr.serve(args.gdb) diff --git a/scripts/opentitan/loghelp.py b/scripts/opentitan/loghelp.py index 2781e9f6f290..8e509976b623 100755 --- a/scripts/opentitan/loghelp.py +++ b/scripts/opentitan/loghelp.py @@ -1,19 +1,23 @@ #!/usr/bin/env python3 -"""Verify register definitions. -""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""Verify register definitions. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser, FileType -from logging import DEBUG, ERROR, getLogger, Formatter, StreamHandler +from logging import getLogger from os.path import basename, splitext from re import compile as re_compile, sub as re_sub from sys import exit as sysexit, modules, stderr from traceback import format_exc from typing import Dict, TextIO, Tuple +from ot.util.log import configure_loggers + REG_CRE = re_compile(r'^#define ([A-Z][\w]+)_REG_(OFFSET|RESVAL)\s+' r'((?:0x)?[A-Fa-f0-9]+)(?:\s|$)') @@ -99,15 +103,7 @@ def main(): args = argparser.parse_args() debug = args.debug - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = Formatter('%(asctime)s.%(msecs)03d %(levelname)8s ' - '%(name)-10s %(message)s', '%H:%M:%S') - log = getLogger('ot') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + configure_loggers(args.verbose, 'ot', ms=True) defs = parse_defs(args.reg) if args.reg else {} check(args.log[0], args.component, defs) diff --git a/scripts/opentitan/mbbdef.py b/scripts/opentitan/mbbdef.py index e988f87a7403..659638991d21 100755 --- a/scripts/opentitan/mbbdef.py +++ b/scripts/opentitan/mbbdef.py @@ -1,13 +1,15 @@ #!/usr/bin/env python3 -"""Find and report multi-bit boolean definitions from HJSON configuration file. -""" - # Copyright (c) 2024, Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""Find and report multi-bit boolean definitions from HJSON configuration file. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser -from logging import DEBUG, ERROR, getLogger, Formatter, StreamHandler +from logging import getLogger from os import walk from os.path import basename, dirname, join as joinpath, splitext from pprint import pprint @@ -15,6 +17,8 @@ from traceback import format_exc from typing import Dict, Iterator, List, TextIO +from ot.util.log import configure_loggers + try: from hjson import load as jload @@ -122,14 +126,7 @@ def main(): args = argparser.parse_args() debug = args.debug - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = Formatter('%(levelname)8s %(name)-10s %(message)s') - log = getLogger('mbb') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + configure_loggers(args.verbose, 'mbb') for hjson in args.ot: mbb = MbbChecker() diff --git a/scripts/opentitan/ot-format.sh b/scripts/opentitan/ot-format.sh index 1c3b9db3e7ab..80f9123a2efc 100755 --- a/scripts/opentitan/ot-format.sh +++ b/scripts/opentitan/ot-format.sh @@ -18,7 +18,8 @@ if [ -z "${clangformat}" ]; then fi # check clang-format version -version_full="$(${clangformat} --version | head -1 | \ +version_full="$(${clangformat} --version | \ + grep "clang-format version" | head -1 | \ sed -E 's/^.*clang-format version ([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')" version_major="$(echo ${version_full} | cut -d. -f1)" if [ ${version_major} -lt ${EXPECTED_VERSION} ]; then @@ -31,7 +32,39 @@ else fi fi -# build config path +CI_MODE=0 +ARGS="" + +# filter arguments +while [ $# -gt 0 ]; do + case "$1" in + --ci) + CI_MODE=1 + ;; + --style=*) + echo "Cannot override --style option" >&2 + exit 1 + ;; + *) + ARGS="$ARGS $1" + ;; + esac + shift +done + +# config +QEMU_ROOT="$(dirname $0)"/../.. CFG="$(dirname $0)"/clang-format.yml +FILES="" + +# automatic file list +if [ $CI_MODE -eq 1 ]; then + # file list path + FILES_D="$(dirname $0)"/clang-format.d + + for filespec in $(cat "$FILES_D"/*.lst); do + FILES="$FILES $QEMU_ROOT/$filespec" + done +fi -exec "${clangformat}" --style=file:"${CFG}" $* +exec "${clangformat}" --style=file:"${CFG}" $ARGS $FILES diff --git a/scripts/opentitan/ot-tidy.sh b/scripts/opentitan/ot-tidy.sh index 9e51a02793d2..9e77b82e15c0 100755 --- a/scripts/opentitan/ot-tidy.sh +++ b/scripts/opentitan/ot-tidy.sh @@ -18,7 +18,8 @@ if [ -z "${clangtidy}" ]; then fi # check clang-tidy version -version_full="$(${clangtidy} --version | head -1 | \ +version_full="$(${clangtidy} --version | \ + grep "LLVM version" | head -1 | \ sed -E 's/^.*LLVM version ([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')" version_major="$(echo ${version_full} | cut -d. -f1)" if [ ${version_major} -lt ${EXPECTED_VERSION} ]; then @@ -31,7 +32,37 @@ else fi fi -# build config path +CI_MODE=0 +ARGS="" + +# filter arguments +while [ $# -gt 0 ]; do + case "$1" in + --ci) + CI_MODE=1 + ;; + --config-file=*) + echo "Cannot override --config-file option" >&2 + exit 1 + ;; + *) + ARGS="$ARGS $1" + ;; + esac + shift +done + +# config +QEMU_ROOT="$(dirname $0)"/../.. CFG="$(dirname $0)"/clang-tidy.yml +FILES_D="$(dirname $0)"/clang-tidy.d +FILES="" + +# automatic file list +if [ $CI_MODE -eq 1 ]; then + for filespec in $(cat "$FILES_D"/*.lst); do + FILES="$FILES $QEMU_ROOT/$filespec" + done +fi -exec "${clangtidy}" --config-file="${CFG}" $* +exec "${clangtidy}" --config-file="${CFG}" $ARGS $FILES diff --git a/scripts/opentitan/ot/__init__.py b/scripts/opentitan/ot/__init__.py new file mode 100644 index 000000000000..dca8c95e274c --- /dev/null +++ b/scripts/opentitan/ot/__init__.py @@ -0,0 +1,4 @@ +"""OpenTitan modules.""" + +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 diff --git a/scripts/opentitan/devproxy.py b/scripts/opentitan/ot/devproxy.py similarity index 95% rename from scripts/opentitan/devproxy.py rename to scripts/opentitan/ot/devproxy.py index a07102235c3e..b0c0d6211f54 100644 --- a/scripts/opentitan/devproxy.py +++ b/scripts/opentitan/ot/devproxy.py @@ -1,9 +1,11 @@ -"""Device proxy for OpenTitan devices and peripherals -""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""Device proxy for OpenTitan devices and peripherals + + :author: Emmanuel Blot +""" + from binascii import hexlify, unhexlify from collections import deque from logging import getLogger @@ -15,6 +17,8 @@ from typing import (Any, Callable, Dict, Iterator, List, NamedTuple, Optional, Tuple, Union) +from .mailbox.doe import DOEHeader + try: from serial import Serial, serial_for_url except ImportError: @@ -86,80 +90,6 @@ def __init__(self): super().__init__(0x201, 'Device On Error') -class DOEHeader: - """Container/helper for DOE headers. - - :param vid: vendor identifier - :param objtype: object type - :param dwlength: count of 32-bit words in the DOE packet (incl. the - header 2x 32-bit words) - """ - - FORMAT = ' str: - return f'vid:0x{self._vid:04x}, objtype:0x{self._objtype:02x}' - - def __repr__(self) -> str: - return f'{self.__class__.__name__} ' \ - f'0x{self._vid:04x},0x{self._objtype:02x}' - - def set_dwlength(self, dwlength: int) -> None: - """Set the actual 32-bit word length of the DOE packet.""" - if not isinstance(dwlength, int) or not 0 <= dwlength <= 0x3ff: - raise ValueError('Invalid dwlength') - self._dwlength = dwlength - - @property - def vid(self): - """Report the stored vendor identifier.""" - return self._vid - - @property - def objtype(self): - """Report the stored object type.""" - return self._objtype - - @property - def dwlength(self): - """Report the count of double words (i.e. 32 bit words) including - the two double words from this very header in the DOE packet. - """ - return self._dwlength - - @classmethod - def decode(cls, buf: bytes) -> 'DOEHeader': - """Decode a byte buffer into a DOE header.""" - if len(buf) < cls.SIZE: - raise ValueError('Too short a buffer') - vid, objtype, length = sunpack(cls.FORMAT, buf) - length &= 0x3ff - return cls(vid, objtype, length) - - def encode(self) -> bytes: - """Encode this DOE header into a byte sequence.""" - buf = spack(self.FORMAT, self._vid, self._objtype, self._dwlength) - return buf - - class MemoryRoot(NamedTuple): """A root memory region. """ diff --git a/scripts/opentitan/ot/dtm/__init__.py b/scripts/opentitan/ot/dtm/__init__.py new file mode 100644 index 000000000000..7304c878e4d9 --- /dev/null +++ b/scripts/opentitan/ot/dtm/__init__.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""Debug Module tools. + + :author: Emmanuel Blot +""" + +from .dtm import DebugTransportModule diff --git a/scripts/opentitan/ot/dtm/dtm.py b/scripts/opentitan/ot/dtm/dtm.py new file mode 100644 index 000000000000..54a64b4d15fb --- /dev/null +++ b/scripts/opentitan/ot/dtm/dtm.py @@ -0,0 +1,325 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""Debug Module tools. + + :author: Emmanuel Blot +""" + + +from logging import getLogger +from sys import modules +from typing import Dict, Optional, Tuple + +# pylint: disable=import-error +from jtag.bits import BitSequence # noqa: E402 +from jtag.jtag import JtagEngine # noqa: E402 + + +class DMIError(RuntimeError): + """DMI Error.""" + + +class DMIBusyError(DMIError): + """Last operation still in progress.""" + + def __init__(self): + super().__init__('DMI is busy') + + +class DMIFailedError(DMIError): + """Last operation has failed.""" + + def __init__(self): + super().__init__('DMI execution failed') + + +class DTMRegister: + """Abstract base class for DTM registers.""" + + def __init__(self, dtm: 'DebugTransportModule'): + name = self.__class__.__name__ + if (not hasattr(self.__class__, 'ADDRESS') or + not isinstance(getattr(self, 'ADDRESS'), int)): + raise NotImplementedError(f'{name} address not defined') + self._dtm = dtm + self._log = getLogger(f'dtm.{name.lower()}') + + @property + def address(self) -> int: + """Return the register address.""" + # pylint: disable=no-member + return self.ADDRESS + + def _read(self, length: int) -> BitSequence: + """Read the current register value.""" + self._log.debug('read %d bits', length) + return self._dtm.read(self.address, length) + + def _write(self, bseq: BitSequence): + """Read the current register value.""" + self._log.debug('write %s', bseq) + return self._dtm.write(self.address, bseq) + + def _read_word(self) -> int: + """Read the current register value as a 32-bit value.""" + self._log.debug('read_word') + return self._dtm.read_word(self.address) + + def _write_word(self, value: int): + """Read the current register value as a 32-bit value.""" + self._log.debug('write_word %x', value) + return self._dtm.write_word(self.address, value) + + +class DTMCS(DTMRegister): + """DTM Control and Status register.""" + + ADDRESS = 0x10 + + @property + def idle(self) -> int: + """Minimum number of cycles a debugger should spend in Run-Test/Idle + after every DMI scan (hint only) + """ + hint = (self._read_word() >> 12) & 0b111 + self._log.debug('idle: %d', hint) + return hint + + @property + def dmistat(self) -> int: + """Return DMI status + + 0: No error. + 1: Reserved. Interpret the same as 2 (see DMI register) + 2: An operation failed (resulted in DMI operation of type 2). + 3: An operation was attempted while a DMI access was still in + progress (resulted in DMI operation of type 3). + """ + dmistat = (self._read_word() >> 10) & 0b11 + self._log.debug('dmistat: %d', dmistat) + return dmistat + + @property + def abits(self) -> int: + """The bit size of address in DMI.""" + abits = (self._read_word() >> 4) & 0b111111 + self._log.debug('abits: %d', abits) + return abits + + @property + def version(self) -> int: + """Version of the supported DMI specification (raw code).""" + version = self._read_word() & 0b1111 + self._log.debug('version: %d', version) + return version + + @property + def dmi_version(self) -> Tuple[int, int]: + """Version of the supported DMI specification.""" + try: + tversion = {0: (0, 11), 1: (0, 13)}[self.version] + except KeyError: + tversion = (0, 0) + self._log.debug('version: %d.%d', *tversion) + return tversion + + def check(self) -> None: + """Raise a DMI Error if any. + """ + self._log.debug('check') + dmistat = self.dmistat + err = self._dtm.build_error(dmistat) + if err: + self._dtm.set_sticky(err) + raise err + + def dmireset(self) -> None: + """Clears the sticky error state and allows the DTM to retry or complete + the previous transaction. + """ + self._log.debug('dmi reset') + self._write_word(1 << 16) + self._dtm.clear_sticky() + + def dmihardreset(self) -> None: + """Causes the DTM to forget about any outstanding DMI transactions. + """ + self._log.debug('dmi hard reset') + self._write_word(1 << 17) + self._dtm.clear_sticky() + + +class DMI(DTMRegister): + """Debug Module Interface Access.""" + + ADDRESS = 0x11 + + OPS = dict(nop=0, read=1, write=2) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._abits = 0 + + @property + def length(self) -> int: + """Return the register length in bits.""" + return self._abits + 32 + 2 + + def write(self, address: int, value: int) -> None: + """Write a 32-bit value to the specified address + """ + dmi = self._build_dmi(address) + value &= 0xffff_ffff + dmi |= value << 2 + dmi |= self.OPS['write'] + wbseq = BitSequence(dmi, self.length) + self._log.info('write: 0x%08x', value) + self._write(wbseq) + rbseq = self._read(self.length) + res = int(rbseq) & 0b11 + err = self._dtm.build_error(res) + if err: + self._log.error('op res %d -> %s', res, err) + self._dtm.set_sticky(err) + raise err + + def read(self, address: int) -> int: + """Read a 32-bit value from the specified address + """ + self._log.info('read @ 0x%x', address) + dmi = self._build_dmi(address) + dmi |= self.OPS['read'] + wbseq = BitSequence(dmi, self.length) + self._write(wbseq) + rbseq = self._read(self.length) + value = int(rbseq) + res = value & 0b11 + err = self._dtm.build_error(res) + if err: + self._log.error('op res %d -> %s', res, err) + self._dtm.set_sticky(err) + raise err + value >>= 2 + value &= 0xffff_ffff + self._log.info('read: 0x%08x', value) + return value + + def _build_dmi(self, address: int) -> int: + self._check_error() + if not self._abits: + self._abits = self._dtm.abits() + if self._abits < 1: + raise DMIError('Invalid reported address bits') + self._log.info('DMI width: %d bits', self._abits) + if address >= (1 << self._abits): + raise ValueError(f'Address 0x{address:x} too large, ' + f'max 0x{(1 << self._abits) -1:x}') + return address << (32 + 2) + + def _check_error(self) -> None: + self._dtm.check_sticky() + + +class DebugTransportModule: + """Debug Transport Modules provide access to the DM over JTAG. + + :param engine: JTAG engine + :param ir_length: the length in bits of the IR register + """ + + # INSTRUCTIONS = dict(dmtcs=DTMCS.ADDRESS, dmi=0x11) + # INSTRUCTIONS.update(JtagController.INSTRUCTIONS) + + def __init__(self, engine: JtagEngine, ir_length: int): + self._engine = engine + self._ir_length = ir_length + self._log = getLogger('dtm') + self._regs = self._load_registers() + self._sticky: Optional[DMIError] = None + + def __getitem__(self, name: str): + try: + return self._regs[name] + except KeyError as exc: + raise ValueError(f"No such DTM reg '{name}'") from exc + + @property + def engine(self) -> JtagEngine: + """Provide the associated engine.""" + return self._engine + + @classmethod + def build_error(cls, code: int) -> Optional[DMIError]: + """Build a DMIError from an error code.""" + if code in (1, 2): + return DMIFailedError() + if code == 3: + return DMIBusyError() + if code == 0: + return None + raise ValueError(f'Invalid DTM error code: {code}') + + def read(self, address: int, length: int) -> BitSequence: + """Read a bit sequence value.""" + self._engine.write_ir(BitSequence(address, self._ir_length)) + self._engine.set_tdi(False) + return self._engine.read_dr(length) + + def write(self, address: int, bseq: BitSequence) -> None: + """Write a bit sequence value.""" + self._engine.write_ir(BitSequence(address, self._ir_length)) + self._engine.write_dr(bseq) + self._engine.run() + + def read_word(self, address: int) -> int: + """Read a 32-bit value.""" + return int(self.read(address, 32)) + + def write_word(self, address: int, value: int) -> int: + """Write a 32-bit value.""" + self.write(address, BitSequence(value, 32)) + + def set_sticky(self, error: DMIError): + """Set sticky error. + @warning Internal API, should not be called but from the DMI + register. + """ + self._sticky = error + + def clear_sticky(self) -> None: + """Clear sticky error. + @warning Internal API, should not be called but from the DMI + register. + """ + self._sticky = None + + def check_sticky(self) -> None: + """Raise a DMIError if a sticky error has been recorded. + """ + if self._sticky: + raise self._sticky + + def abits(self) -> int: + """Report the bit size of address in DMI.""" + try: + dtmcs = self['dtmcs'] + except KeyError as exc: + raise DMIError('Missing DTMCS register') from exc + return dtmcs.abits + + def _load_registers(self) -> Dict[str, DTMRegister]: + module = modules[__name__] + regs = {} + for name in dir(module): + class_ = getattr(module, name) + if not isinstance(class_, type): + continue + if not issubclass(class_, DTMRegister) or class_ is DTMRegister: + continue + address = getattr(class_, 'ADDRESS', None) + if not address or not isinstance(address, int): + continue + self._log.debug('Instanciate %s', name) + regs[name.lower()] = class_(self) + return regs diff --git a/scripts/opentitan/ot/lc_ctrl/__init__.py b/scripts/opentitan/ot/lc_ctrl/__init__.py new file mode 100644 index 000000000000..c7a9e406c921 --- /dev/null +++ b/scripts/opentitan/ot/lc_ctrl/__init__.py @@ -0,0 +1,8 @@ +"""LifeCycle tools.""" + +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + + +class LifeCycleError(RuntimeError): + """Life Cycle Error""" diff --git a/scripts/opentitan/ot/lc_ctrl/lcdmi.py b/scripts/opentitan/ot/lc_ctrl/lcdmi.py new file mode 100644 index 000000000000..d47c3baffb25 --- /dev/null +++ b/scripts/opentitan/ot/lc_ctrl/lcdmi.py @@ -0,0 +1,338 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""LifeCycle DMI. + + :author: Emmanuel Blot +""" + +from binascii import Error as BinasciiError, hexlify, unhexlify +from logging import getLogger +from struct import pack as spack, unpack as sunpack +from typing import Dict, NamedTuple, Tuple + +from . import LifeCycleError +from ..dtm import DebugTransportModule +from ..util.mbb import MB8_TRUE, MB8_FALSE, MB8_MASK + + +class HardwareRevision(NamedTuple): + """OpenTitan Hardware Revision.""" + silicon_creator: int + product_id: int + revision_id: int + + +class LifeCycleController: + """LifeCycle Controller over DMI.""" + + STATUS = """ + initialized + ready + ext_clock_switched + transition_successful + transition_count_error + transition_error + token_error + flash_rma_error + otp_error + state_error + bus_integ_error + otp_partition_error + """.split() + """Status bits.""" + + STATES = """ + RAW + TEST_UNLOCKED0 + TEST_LOCKED0 + TEST_UNLOCKED1 + TEST_LOCKED1 + TEST_UNLOCKED2 + TEST_LOCKED2 + TEST_UNLOCKED3 + TEST_LOCKED3 + TEST_UNLOCKED4 + TEST_LOCKED4 + TEST_UNLOCKED5 + TEST_LOCKED5 + TEST_UNLOCKED6 + TEST_LOCKED6 + TEST_UNLOCKED7 + DEV + PROD + PROD_END + RMA + SCRAP + """.split() + + REGS = dict(alert_test=0, status=1, claim_transition_if_regwen=2, + claim_transition_if=3, transition_regwen=4, transition_cmd=5, + transition_ctrl=6, transition_token=7, transition_target=11, + otp_vendor_test_ctrl=12, otp_vendor_test_status=13, lc_state=14, + lc_transition_cnt=15, lc_id_state=16, hw_revision=17, + device_id=19, manuf_state=27) + """Registers.""" + + ALERTS = 'prog_error state_error bus_integ_error'.split() + """Alerts.""" + + TOKEN_FORMAT = '<4I' + + def __init__(self, dtm: DebugTransportModule, address: int): + super().__init__() + self._log = getLogger('dtm.lcctrl') + self._dtm = dtm + self._dmi = dtm['dmi'] + self._address = address + self._hw_rev_widths = (16, 16, 8) + + def restart_system(self) -> None: + """Restart the remote machine.""" + self._dtm.engine.controller.system_reset() + + def set_alert_test(self, alert: str) -> None: + """Test alert.""" + try: + alix = self.ALERTS.index(alert.lower()) + except IndexError as exc: + raise ValueError(f'No such alert {alert}') from exc + self._write_reg('alert_test', 1 << alix) + + @property + def status(self) -> Dict[str, bool]: + """Retrieve the current status.""" + value = self._read_reg('status') + status = {self.STATUS[b]: bool(value & (1 << b)) + for b in range(len(self.STATUS))} + return status + + def disable_claim_transition_if_regwen(self): + """Disable claim transition interface.""" + self._write_reg('claim_transition_if_regwen', 0) + + def claim_transition_if(self, claim: bool) -> bool: + """Clain transition interface. + + :return: True of the interface has been successfully claimed for DMI. + """ + reg = 'claim_transition_if' + self._log.debug('%s interface', 'Claim' if claim else 'Release') + if claim: + self._write_reg(reg, MB8_TRUE) + val = self._read_reg(reg) & MB8_MASK + success = val == MB8_TRUE + return success + self._write_reg(reg, MB8_FALSE) + val = self._read_reg(reg) & MB8_MASK + if val == MB8_TRUE: + raise LifeCycleError('Cannot release LC interface') + return val == MB8_FALSE + + @property + def transition_regwen(self) -> bool: + """Tells whether transition registers can be written.""" + regwen = bool(self._read_reg('transition_regwen') & 0x1) + self._log.debug('Transition regwen: %s', regwen) + return regwen + + def transition_start(self) -> str: + """Start the transition operation.""" + self._log.debug('Start transition') + self._write_reg('transition_cmd', 0b1) + + @property + def volatile_raw_unlock(self) -> bool: + """Report whether volatile unlock is enabled.""" + reg = 'volatile_raw_unlock' + vru = bool(self._read_reg(reg) & 0b1) + return vru + + @volatile_raw_unlock.setter + def volatile_raw_unlock(self, enable: bool) -> None: + """Enable or disable volatile unlock.""" + reg = 'transition_ctrl' + value = self._read_reg(reg) + if enable: + value |= 0b10 + else: + value &= ~0b10 + self._write_reg(reg, value) + + @property + def ext_clock_en(self) -> bool: + """Report whether external clock is selected.""" + reg = 'transition_ctrl' + value = self._read_reg(reg) + value |= 0b1 + self._write_reg(reg, value) + + @ext_clock_en.setter + def ext_clock_en(self) -> None: + """Select external clock source.""" + + @property + def transition_token(self) -> bytes: + """Report current transition token.""" + tokens = (self._read_reg('transition_token', pos) for pos in range(4)) + token = spack(self.TOKEN_FORMAT, *tokens) + self._log.debug('Transition token: %s', hexlify(token).decode()) + return token + + @transition_token.setter + def transition_token(self, token: [bytes | bytearray | str | None]) -> None: + """Define the transition token as a 16-byte token. + + :param token: if None, use an empty zeroed token, + if provided as a string, it should be an hexadecimal + value of 32 characters, otherwise it should be a + 16-byte sequence. + """ + if isinstance(token, str): + try: + token = unhexlify(token) + except BinasciiError as exc: + raise ValueError('Invalid token string: {exc}') from exc + elif token is None: + token = bytes(16) + elif not isinstance(token, (bytes, bytearray)): + raise ValueError('Invalid token type') + if len(token) != 16: + raise ValueError('Invalid token length') + token = bytes(reversed(token)) + for tix, tok in enumerate(sunpack('<4I', token)): + self._log.debug('Write token[%d] 0x%08x', tix, tok) + self._write_reg('transition_token', tok, tix) + + @property + def transition_target(self) -> Tuple[str, int]: + """Read back the transition target.""" + target = self._read_reg('transition_target') + starget = self._decode_state(target) + self._log.debug('Transition target: %s', starget) + return starget, target + + @transition_target.setter + def transition_target(self, target: [str | int]) -> None: + """Define the transition token as a 16-byte token.""" + if isinstance(target, str): + itarget = self._encode_state(target) + elif isinstance(target, int): + if target < (1 << 5): + itarget = self._expand_state(target) + else: + itarget = target + self._check_state(itarget) + else: + raise ValueError('Invalid target type') + self._log.debug('Set transition target: 0x%08x', itarget) + self._write_reg('transition_target', itarget) + + def otp_vendor_test_ctrl(self) -> int: + """Provide the OTP vendor test control as a 32-bit value.""" + return self._read_reg('otp_vendor_test_ctrl') + + def otp_vendor_test_status(self) -> int: + """Provide the OTP vendor test status as a 32-bit value.""" + return self._read_reg('otp_vendor_test_status') + + @property + def lc_state(self) -> [str | int]: + """Report the current state.""" + istate = self._read_reg('lc_state') + tix = self._check_state(istate) + return self.STATES[tix], istate + + @property + def lc_transition_count(self) -> int: + """Report the current transition count.""" + return self._read_reg('lc_transition_cnt') & 0x1f + + @property + def lc_id_state(self) -> str: + """Report the current ID state.""" + value = self._read_reg('lc_id_state') + idmap = {0: 'blank', 0x55555555: 'personalized', 0xaaaaaaaa: 'invalid'} + try: + return idmap[value] + except KeyError as exc: + raise LifeCycleError(f'Unknown ID state 0x{value:08x}') from exc + + @property + def hw_revision(self) -> HardwareRevision: + """Report the HW revision.""" + hw0 = self._read_reg('hw_revision', 0) + hw1 = self._read_reg('hw_revision', 1) + widths = self._hw_rev_widths + creator = hw0 >> widths[1] & ((1 << widths[0]) - 1) + product = hw0 & ((1 << widths[1]) - 1) + revision = hw1 & ((1 << widths[2]) - 1) + return HardwareRevision(creator, product, revision) + + @property + def device_identifier(self) -> bytes: + """Report the device identifier as a 32-byte value.""" + devids = (self._read_reg('device_id', pos) for pos in range(8)) + devid = spack(self.TOKEN_FORMAT, *devids) + self._log.debug('Transition token: %s', hexlify(devid).decode()) + return devid + + @property + def manufacturer_state(self) -> bytes: + """Report the manufacturer state as a 32-byte value.""" + devids = (self._read_reg('manuf_state', pos) for pos in range(8)) + devid = spack(self.TOKEN_FORMAT, *devids) + self._log.debug('Transition token: %s', hexlify(devid).decode()) + return devid + + @classmethod + def _decode_state(cls, state: int) -> str: + tgix = cls._check_state(state) + return cls.STATES[tgix] + + @classmethod + def _encode_state(cls, state: str) -> int: + try: + tgix = cls.STATES.index(state.upper()) + except IndexError as exc: + raise ValueError(f"Unknwon state '{state}'") from exc + return cls._expand_state(tgix) + + @classmethod + def _check_state(cls, state: int) -> int: + base = cls._base_state(state) + if cls._expand_state(state) != state: + raise ValueError(f'Unknown state {state:08x}') + if not 0 <= base < len(cls.STATES): + raise ValueError(f'Unknown state {state:08x}') + return base + + @classmethod + def _base_state(cls, state: int) -> int: + return state & ((1 << 5) - 1) + + @classmethod + def _expand_state(cls, state: int) -> int: + base = cls._base_state(state) + return ((base << 25) | (base << 20) | (base << 15) | (base << 10) | + (base << 5) | base) + + def _write_reg(self, name: str, value: int, offset: int = 0) -> None: + if value >= (1 << 32): + raise ValueError('Invalid value') + try: + reg = self.REGS[name] + offset + except KeyError as exc: + raise ValueError(f"No such LC register: '{name}'") from exc + self._log.info('write %s: 0x%08x', name, value) + return self._dmi.write(self._address + reg, value) + + def _read_reg(self, name: str, offset: int = 0) -> int: + try: + reg = self.REGS[name] + offset + except KeyError as exc: + raise ValueError(f"No such LC register: '{name}'") from exc + self._log.info('read %s', name) + value = self._dmi.read(self._address + reg) + self._log.info('read 0x%08x', value) + return value diff --git a/scripts/opentitan/ot/mailbox/__init__.py b/scripts/opentitan/ot/mailbox/__init__.py new file mode 100644 index 000000000000..7fbe72811a0d --- /dev/null +++ b/scripts/opentitan/ot/mailbox/__init__.py @@ -0,0 +1,4 @@ +"""Mailbox tools.""" + +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 diff --git a/scripts/opentitan/ot/mailbox/doe.py b/scripts/opentitan/ot/mailbox/doe.py new file mode 100644 index 000000000000..003a9d5538d8 --- /dev/null +++ b/scripts/opentitan/ot/mailbox/doe.py @@ -0,0 +1,162 @@ +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""Device proxy for OpenTitan devices and peripherals + + :author: Emmanuel Blot +""" + +from logging import getLogger +from struct import calcsize as scalc, pack as spack, unpack as sunpack +from typing import Tuple + +from .sysmbox import SysMbox, SysMboxError + + +class DOEHeader: + """Container/helper for DOE headers. + + :param vid: vendor identifier + :param objtype: object type + :param dwlength: count of 32-bit words in the DOE packet (incl. the + header 2x 32-bit words) + """ + + FORMAT = ' str: + return f'vid:0x{self._vid:04x}, objtype:0x{self._objtype:02x}' + + def __repr__(self) -> str: + return f'{self.__class__.__name__} ' \ + f'0x{self._vid:04x},0x{self._objtype:02x}' + + def set_dwlength(self, dwlength: int) -> None: + """Set the actual 32-bit word length of the DOE packet.""" + if not isinstance(dwlength, int) or not 0 <= dwlength <= 0x3ff: + raise ValueError('Invalid dwlength') + self._dwlength = dwlength + + @property + def vid(self): + """Report the stored vendor identifier.""" + return self._vid + + @property + def objtype(self): + """Report the stored object type.""" + return self._objtype + + @property + def dwlength(self): + """Report the count of double words (i.e. 32 bit words) including + the two double words from this very header in the DOE packet. + """ + return self._dwlength + + @classmethod + def decode(cls, buf: bytes) -> 'DOEHeader': + """Decode a byte buffer into a DOE header.""" + if len(buf) < cls.SIZE: + raise ValueError('Too short a buffer') + vid, objtype, length = sunpack(cls.FORMAT, buf) + length &= 0x3ff + return cls(vid, objtype, length) + + def encode(self) -> bytes: + """Encode this DOE header into a byte sequence.""" + buf = spack(self.FORMAT, self._vid, self._objtype, self._dwlength) + return buf + + +class DOEMailbox: + """Mailbox with a DOE header. + + :param mailbox: a system mailbox instance + :param vid: vendor ID for the DOE header + """ + + def __init__(self, mailbox: SysMbox, vid: int): + self._mbox = mailbox + self._vid = vid + self._log = getLogger('mbox.doe') + + def abort(self): + """Tell the mailbox to abort the request / clear any error.""" + self._mbox.abort() + + @property + def busy(self) -> bool: + """Report whether the mailbox is busy.""" + return self._mbox.busy + + @property + def on_error(self) -> bool: + """Report whether the mailbox is on error.""" + return self._mbox.on_error + + @property + def object_ready(self) -> bool: + """Report whether the mailbox contains a response.""" + return self._mbox.object_ready + + def write(self, oid: int, msg: bytes) -> None: + """Send a DOE message.""" + hdr = DOEHeader(self._vid, oid) + trailing = len(msg) & 0x3 + if trailing: + msg = b''.join((msg, bytes(4-trailing))) + dwlen = len(msg)//4 + DOEHeader.DWSIZE + hdr.set_dwlength(dwlen) + req = b''.join((hdr.encode(), msg)) + self._log.debug('len %d', len(req)) + count = self._mbox.write(req) + if count != len(req): + raise SysMboxError(f'Cannot write full buffer {count}/{len(req)}') + if self._mbox.on_error: + raise SysMboxError('JTAG mailbox on error') + + def read(self) -> Tuple[int, bytes]: + """Receive a DOE message.""" + resp = self._mbox.read() + if not resp: + raise SysMboxError('No response from host') + if len(resp) < DOEHeader.SIZE: + raise SysMboxError('Truncated response from host') + self._log.debug('len %d', len(resp)) + hdr = DOEHeader.decode(resp[:DOEHeader.SIZE]) + if hdr.vid != self._vid: + raise SysMboxError(f'Unexpected vendor ID 0x{hdr.vid:04x}') + plen = (hdr.dwlength - DOEHeader.DWSIZE) * 4 + payload = resp[DOEHeader.SIZE:] + if plen != len(payload): + raise SysMboxError(f'Unexpected payload length ' + f'{plen}/{len(payload)}') + oid = hdr.objtype + return oid, payload + + def exchange(self, oid: int, msg: bytes) -> bytes: + """Exchange a message/response on the mailbox.""" + self.write(oid, msg) + roid, payload = self.read() + if roid != oid: + raise SysMboxError(f'Unexpected object type: {oid}/{roid}') + return payload diff --git a/scripts/opentitan/ot/mailbox/jtag.py b/scripts/opentitan/ot/mailbox/jtag.py new file mode 100644 index 000000000000..63520f3115d5 --- /dev/null +++ b/scripts/opentitan/ot/mailbox/jtag.py @@ -0,0 +1,79 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""Mailbox over JTAG access. + + :author: Emmanuel Blot +""" + +from logging import getLogger + +# see scripts/jtag +# pylint: disable=import-error +# pylint: disable=unused-import +from jtag.jtag import JtagError # noqa: F401 +from .sysmbox import SysMbox +from ..dtm import DebugTransportModule + + +class JtagMbox(SysMbox): + """JTAG Mailbox requester API + """ + + SYSREGS = dict(control=2, status=3, wdata=4, rdata=5) + + def __init__(self, dtm: 'DebugTransportModule', address: int): + super().__init__() + self._log = getLogger('dtm.jtagmbx') + self._dmi = dtm['dmi'] + self._address = address + + @property + def busy(self) -> bool: + return bool(self._read_reg('status') & 0b001) + + @property + def on_error(self) -> bool: + return bool(self._read_reg('status') & 0b100) + + @property + def object_ready(self) -> bool: + return bool(self._read_reg('status') >> 31) + + def go(self) -> None: + self._write_reg('control', 1 << 31) + + def abort(self) -> None: + self._write_reg('control', 0b1) + + def write_word(self, word: int) -> None: + self._write_reg('wdata', word) + + def read_word(self, ack: bool = True) -> int: + word = self._read_reg('rdata') + if ack: + self.acknowledge_read() + return word + + def acknowledge_read(self) -> None: + self._write_reg('rdata', 0) # value is meaningless + + def _write_reg(self, name: str, value: int) -> None: + if value >= (1 << 32): + raise ValueError('Invalid value') + try: + reg = self.SYSREGS[name] + except KeyError as exc: + raise ValueError(f"No such mailbox register: '{name}'") from exc + self._log.info('write %s: 0x%08x', name, value) + return self._dmi.write(self._address + reg, value) + + def _read_reg(self, name: str) -> int: + try: + reg = self.SYSREGS[name] + except KeyError as exc: + raise ValueError(f"No such mailbox register: '{name}'") from exc + self._log.info('read %s', name) + value = self._dmi.read(self._address + reg) + self._log.info('read 0x%08x', value) + return value diff --git a/scripts/opentitan/ot/mailbox/sysmbox.py b/scripts/opentitan/ot/mailbox/sysmbox.py new file mode 100644 index 000000000000..b45d0b3c735a --- /dev/null +++ b/scripts/opentitan/ot/mailbox/sysmbox.py @@ -0,0 +1,105 @@ +"""System Mailbox. + + :author: Emmanuel Blot +""" + +from binascii import hexlify +from logging import getLogger +from time import sleep, time as now + + +class SysMboxError(RuntimeError): + """System mailbox error.""" + + +class SysMbox: + """Mailbox requester API + """ + def __init__(self): + self._log = getLogger('mbox.sys') + + @property + def busy(self) -> bool: + """Report whether the mailbox is busy.""" + raise NotImplementedError('ABC') + + @property + def on_error(self) -> bool: + """Report whether the mailbox is on error.""" + raise NotImplementedError('ABC') + + @property + def object_ready(self) -> bool: + """Report whether the mailbox contains a response.""" + raise NotImplementedError('ABC') + + def go(self) -> None: + """Tell the mailbox to process the request.""" + # pylint: disable=invalid-name + raise NotImplementedError('ABC') + + def abort(self) -> None: + """Tell the mailbox to abort the request / clear any error.""" + raise NotImplementedError('ABC') + + def write_word(self, word: int) -> None: + """Write a single request word into the mailbox. + + It is the caller responsability to check the mailbox is ready to + receive a new word. + """ + raise NotImplementedError('ABC') + + def read_word(self, ack: bool = True) -> int: + """Read a single response word from the mailbox. + + It is the caller responsability to check the mailbox contains a new + word. + """ + raise NotImplementedError('ABC') + + def acknowledge_read(self) -> None: + """Acknowledge the read out of the last retrieved word.""" + raise NotImplementedError('ABC') + + def write(self, request: bytes) -> int: + """Send a request to the mailbox.""" + if self.busy: + raise SysMboxError('Mailbox is busy') + if self.on_error: + raise SysMboxError('Mailbox is on error') + trailing = len(request) & 0x3 + if trailing: + request = b''.join((request, bytes(4-trailing))) + self._log.info('TX: (%d) %s', len(request), hexlify(request).decode()) + reqlen = 0 + while request: + chunk, request = request[:4], request[4:] + self.write_word(int.from_bytes(chunk, 'little')) + reqlen += 4 + self.go() + return reqlen + + def read(self) -> bytes: + """Receive a response from the mailbox.""" + timeout = now() + 2.0 + while True: + if self.on_error: + self.abort() + raise SysMboxError('Mailbox is on error') + if self.object_ready: + break + if now() > timeout: + raise TimeoutError('No response from mailbox') + sleep(0.1) + response = bytearray() + while self.object_ready: + chunk = self.read_word() + response.extend(chunk.to_bytes(4, 'little')) + self._log.info('RX: (%d) %s', len(response), hexlify(response).decode()) + return bytes(response) + + def exchange(self, request: bytes) -> bytes: + """Performs a full half-duplex response-request on the mailbox.""" + self.write(request) + return self.read() diff --git a/scripts/opentitan/ot/util/__init__.py b/scripts/opentitan/ot/util/__init__.py new file mode 100644 index 000000000000..890797d26e79 --- /dev/null +++ b/scripts/opentitan/ot/util/__init__.py @@ -0,0 +1,4 @@ +"""Utilities.""" + +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 diff --git a/scripts/opentitan/ot/util/log.py b/scripts/opentitan/ot/util/log.py new file mode 100644 index 000000000000..6189bf92e71e --- /dev/null +++ b/scripts/opentitan/ot/util/log.py @@ -0,0 +1,93 @@ +"""Logging helpers. +""" + +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +from logging import (Formatter, Logger, StreamHandler, CRITICAL, DEBUG, INFO, + ERROR, WARNING, getLogger) +from os import isatty +from sys import stderr +from typing import List + + +class ColorLogFormatter(Formatter): + """Custom log formatter for ANSI terminals. + Colorize log levels. + + Optional features: + * 'time' (boolean): prefix log messsages with 24h HH:MM:SS time + * 'ms' (boolean): prefix log messages with 24h HH:MM:SS.msec time + * 'lineno'(boolean): show line numbers + * 'name_width' (int): padding width for logger names + * 'color' (boolean): enable/disable log level colorization + """ + + GREY = "\x1b[38;20m" + YELLOW = "\x1b[33;1m" + RED = "\x1b[31;1m" + MAGENTA = "\x1b[35;1m" + WHITE = "\x1b[37;1m" + RESET = "\x1b[0m" + FMT_LEVEL = '%(levelname)8s' + + COLORS = { + DEBUG: GREY, + INFO: WHITE, + WARNING: YELLOW, + ERROR: RED, + CRITICAL: MAGENTA, + } + + def __init__(self, *args, **kwargs): + kwargs = dict(kwargs) + name_width = kwargs.pop('name_width', 10) + self._use_ansi = kwargs.pop('color', isatty(stderr.fileno())) + use_ms = kwargs.pop('ms', False) + use_time = kwargs.pop('time', use_ms) + use_lineno = kwargs.pop('lineno', False) + super().__init__(*args, **kwargs) + format_trail = f' %(name)-{name_width}s %(message)s' + if use_time: + tfmt = '%(asctime)s ' if not use_ms else '%(asctime)s.%(msecs)03d ' + else: + tfmt = '' + lno = ' [%(lineno)d] ' if use_lineno else '' + self._plain_format = f'{tfmt}{self.FMT_LEVEL}{lno}{format_trail}' + self._color_formats = { + lvl: f'{tfmt}{clr}{self.FMT_LEVEL}{self.RESET}{lno}{format_trail}' + for lvl, clr in self.COLORS.items() + } + self._formatter_args = ['%H:%M:%S'] if use_time else [] + + def format(self, record): + log_fmt = self._color_formats[record.levelno] if self._use_ansi \ + else self._plain_format + formatter = Formatter(log_fmt, *self._formatter_args) + return formatter.format(record) + + +def configure_loggers(level: int, *lognames: List[str], **kwargs) \ + -> List[Logger]: + """Configure loggers. + + :param level: level (stepping: 1) + :param lognames: one or more loggers to configure + :param kwargs: optional features + :return: configured loggers or level change + """ + loglevel = ERROR - (10 * (level or 0)) + loglevel = min(ERROR, loglevel) + formatter = ColorLogFormatter(**kwargs) + logh = StreamHandler(stderr) + logh.setFormatter(formatter) + loggers: List[Logger] = [] + for logdef in lognames: + if isinstance(logdef, int): + loglevel += -10 * logdef + continue + log = getLogger(logdef) + log.setLevel(max(DEBUG, loglevel)) + log.addHandler(logh) + loggers.append(log) + return loggers diff --git a/scripts/opentitan/ot/util/mbb.py b/scripts/opentitan/ot/util/mbb.py new file mode 100644 index 000000000000..215f2d7a8539 --- /dev/null +++ b/scripts/opentitan/ot/util/mbb.py @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""MultiBit Boolean values + + :author: Emmanuel Blot +""" + +MB4_TRUE = 0x6 +MB4_FALSE = 0x9 +MB4_MASK = 0xf + +MB8_TRUE = 0x96 +MB8_FALSE = 0x89 +MB8_MASK = 0xff diff --git a/scripts/opentitan/otphelp.py b/scripts/opentitan/otphelp.py index b637a2178c07..97a23578e113 100755 --- a/scripts/opentitan/otphelp.py +++ b/scripts/opentitan/otphelp.py @@ -1,24 +1,30 @@ #!/usr/bin/env python3 -"""OpenTitan OTP HJSON helper +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""OpenTitan OTP HJSON helper. + + :note: this script is deprecated and should be merged into otptool.py + + :author: Emmanuel Blot """ -# Copyright (c) 2023 Rivos, Inc. -# SPDX-License-Identifier: Apache2 -from argparse import ArgumentParser, FileType, Namespace +from argparse import ArgumentParser, FileType try: # try to use HJSON if available from hjson import load as jload except ImportError as _exc: raise ImportError("HJSON Python module required") from _exc -from logging import (Formatter, StreamHandler, CRITICAL, DEBUG, INFO, ERROR, - WARNING, getLogger) +from logging import getLogger from os import linesep from pprint import pprint from sys import exit as sysexit, modules, stderr from traceback import format_exc -from typing import BinaryIO, Optional +from typing import BinaryIO + +from ot.util.log import configure_loggers class OtpHelper: @@ -132,15 +138,7 @@ def main(): args = argparser.parse_args() debug = args.debug - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = Formatter('%(levelname)8s [%(lineno)d] %(name)-12s ' - '%(message)s') - log = getLogger('otp') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + configure_loggers('otp', args.verbose, name_width=12, lineno=True) otp = OtpHelper() otp.load(args.config) diff --git a/scripts/opentitan/otptool.py b/scripts/opentitan/otptool.py index f49cb6393181..eb66c5c37fe4 100755 --- a/scripts/opentitan/otptool.py +++ b/scripts/opentitan/otptool.py @@ -1,15 +1,17 @@ #!/usr/bin/env python3 -"""QEMU OT tool to manage OTP files. -""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""QEMU OT tool to manage OTP files. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser, FileType from binascii import hexlify, unhexlify from io import BytesIO, StringIO -from logging import DEBUG, ERROR, getLogger, Formatter, StreamHandler +from logging import getLogger from os.path import basename from re import match as re_match, sub as re_sub from struct import calcsize as scalc, pack as spack, unpack as sunpack @@ -19,6 +21,8 @@ from typing import (Any, BinaryIO, Dict, Iterator, List, Optional, Set, TextIO, Tuple, Union) +from ot.util.log import configure_loggers + try: # try to load HJSON if available from hjson import load as hjload @@ -997,14 +1001,7 @@ def main(): args = argparser.parse_args() debug = args.debug - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = Formatter('%(levelname)8s %(name)-10s %(message)s') - log = getLogger('otptool') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + configure_loggers(args.verbose, 'otptool') otp = OtpImage(args.ecc) diff --git a/scripts/opentitan/pyot.py b/scripts/opentitan/pyot.py index 43b0a95fb374..899704e952aa 100755 --- a/scripts/opentitan/pyot.py +++ b/scripts/opentitan/pyot.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 -"""OpenTitan QEMU test sequencer. -""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""OpenTitan QEMU unit test sequencer. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser, FileType, Namespace from atexit import register from collections import defaultdict @@ -18,17 +20,15 @@ except ImportError: # fallback on legacy JSON syntax otherwise from json import load as jload -from logging import (Formatter, StreamHandler, CRITICAL, DEBUG, INFO, ERROR, - WARNING, getLogger) -from os import (close, curdir, environ, getcwd, isatty, linesep, pardir, sep, - unlink) +from logging import CRITICAL, DEBUG, INFO, ERROR, getLogger +from os import close, curdir, environ, getcwd, linesep, pardir, sep, unlink from os.path import (abspath, basename, dirname, isabs, isdir, isfile, join as joinpath, normpath, relpath) from re import Match, compile as re_compile, sub as re_sub from shutil import rmtree from socket import socket, timeout as LegacyTimeoutError from subprocess import Popen, PIPE, TimeoutExpired -from sys import argv, exit as sysexit, modules, stderr, stdout +from sys import argv, exit as sysexit, modules, stderr from threading import Thread from tempfile import mkdtemp, mkstemp from time import time as now @@ -36,6 +36,8 @@ from typing import (Any, Deque, Dict, Iterator, List, NamedTuple, Optional, Set, Tuple) +from ot.util.log import configure_loggers + DEFAULT_MACHINE = 'ot-earlgrey' DEFAULT_DEVICE = 'localhost:8000' @@ -61,40 +63,6 @@ class TestResult(NamedTuple): error: str -class CustomFormatter(Formatter): - """Custom log formatter for ANSI terminals. Colorize log levels. - """ - - GREY = "\x1b[38;20m" - YELLOW = "\x1b[33;1m" - RED = "\x1b[31;1m" - MAGENTA = "\x1b[35;1m" - WHITE = "\x1b[37;1m" - RESET = "\x1b[0m" - FORMAT_LEVEL = '%(levelname)8s' - FORMAT_TRAIL = ' %(name)-10s %(message)s' - - COLOR_FORMATS = { - DEBUG: f'{GREY}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - INFO: f'{WHITE}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - WARNING: f'{YELLOW}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - ERROR: f'{RED}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - CRITICAL: f'{MAGENTA}{FORMAT_LEVEL}{RESET}{FORMAT_TRAIL}', - } - - PLAIN_FORMAT = f'{FORMAT_LEVEL}{FORMAT_TRAIL}' - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self._istty = isatty(stdout.fileno()) - - def format(self, record): - log_fmt = self.COLOR_FORMATS[record.levelno] if self._istty \ - else self.PLAIN_FORMAT - formatter = Formatter(log_fmt) - return formatter.format(record) - - class ResultFormatter: """Format a result CSV file as a simple result table.""" @@ -211,7 +179,7 @@ def run(self, qemu_args: List[str], timeout: int, name: str, try: # ensure that QEMU starts and give some time for it to set up # its VCP before attempting to connect to it - self._log.debug(f'Waiting {start_delay:.1f}s for VM init') + self._log.debug('Waiting %.1fs for VM init', start_delay) proc.wait(start_delay) except TimeoutExpired: pass @@ -737,7 +705,7 @@ def command(self) -> str: def _run(self): self._resume = True - #pylint: disable=consider-using-with + # pylint: disable=consider-using-with proc = Popen(self._cmd, bufsize=1, stdout=PIPE, stderr=PIPE, shell=True, env=self._env, encoding='utf-8', errors='ignore', text=True) @@ -941,6 +909,11 @@ class QEMUExecuter: QEMUWrapper.NO_MATCH_RETURN_CODE: 'UNKNOWN', } + DEFAULT_START_DELAY = 1.0 + """Default start up delay to let QEMU initialize before connecting the + virtual UART port. + """ + def __init__(self, qfm: QEMUFileManager, config: Dict[str, any], args: Namespace): self._log = getLogger('pyot.exec') @@ -993,7 +966,8 @@ def run(self, debug: bool) -> int: DEFAULT_TIMEOUT_FACTOR)))) self._log.debug('Execute %s', basename(self._argdict['exec'])) ret, xtime, err = qot.run(self._qemu_cmd, timeout, - self.get_test_radix(app), None) + self.get_test_radix(app), None, + self.DEFAULT_START_DELAY) results[ret] += 1 sret = self.RESULT_MAP.get(ret, ret) icount = self._argdict.get('icount') @@ -1156,8 +1130,8 @@ def _build_qemu_command(self, args: Namespace, if not isfile(args.flash): raise ValueError(f'No such flash file: {args.flash}') if any((args.exec, args.boot)): - raise ValueError('Flash file argument is mutually exclusive with' - ' bootloader or rom extension') + raise ValueError('Flash file argument is mutually exclusive ' + 'with bootloader or rom extension') flash_path = self.abspath(args.flash) qemu_args.extend(('-drive', f'if=mtd,bus=1,file={flash_path},' f'format=raw')) @@ -1188,7 +1162,8 @@ def _build_qemu_command(self, args: Namespace, qemu_args.extend(('-icount', f'{args.icount}')) mux = f'mux={"on" if args.muxserial else "off"}' try: - start_delay = float(getattr(args, 'start_delay', 1.0)) + start_delay = float(getattr(args, 'start_delay') or\ + self.DEFAULT_START_DELAY) except ValueError as exc: raise ValueError(f'Invalid start up delay {args.start_delay}') \ from exc @@ -1475,14 +1450,7 @@ def main(): close(tmpfd) args.result = tmp_result - loglevel = max(DEBUG, ERROR - (10 * (args.verbose or 0))) - loglevel = min(ERROR, loglevel) - formatter = CustomFormatter() - log = getLogger('pyot') - logh = StreamHandler(stderr) - logh.setFormatter(formatter) - log.setLevel(loglevel) - log.addHandler(logh) + log = configure_loggers(args.verbose, 'pyot')[0] qfm = QEMUFileManager(args.keep_tmp) diff --git a/scripts/opentitan/swexit.py b/scripts/opentitan/swexit.py index 5e240bd837b9..efbd236120b4 100755 --- a/scripts/opentitan/swexit.py +++ b/scripts/opentitan/swexit.py @@ -1,10 +1,13 @@ #!/usr/bin/env python3 -"""OpenTitan exit code generator for QEMU.""" - # Copyright (c) 2023-2024 Rivos, Inc. # SPDX-License-Identifier: Apache2 +"""OpenTitan exit code generator for QEMU. + + :author: Emmanuel Blot +""" + from argparse import ArgumentParser, FileType from struct import pack as spack from sys import exit as sysexit, modules, stderr, stdout diff --git a/scripts/opentitan/treillis/boot.py b/scripts/opentitan/treillis/boot.py index 8ab87f79426a..931aa4bfe58c 100644 --- a/scripts/opentitan/treillis/boot.py +++ b/scripts/opentitan/treillis/boot.py @@ -1,3 +1,10 @@ +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""Configuration file for CircuitPython.""" + +# pylint: disable=import-error + import usb_cdc import usb_midi diff --git a/scripts/opentitan/treillis/code.py b/scripts/opentitan/treillis/code.py index bba2935bea4f..bdd67ee9966a 100644 --- a/scripts/opentitan/treillis/code.py +++ b/scripts/opentitan/treillis/code.py @@ -1,12 +1,17 @@ +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + """Simple CircuitPython script (which is stuck with Python 3.4) that maps QEMU GPIO chardev backend device onto a NeoTreillis M4 Express device. + + :author: Emmanuel Blot """ -#pylint: disable=import-error -#pylint: disable=invalid-name -#pylint: disable=missing-function-docstring -#pylint: disable=consider-using-f-string -#pylint: disable=missing-class-docstring +# pylint: disable=import-error +# pylint: disable=invalid-name +# pylint: disable=missing-function-docstring +# pylint: disable=consider-using-f-string +# pylint: disable=missing-class-docstring try: @@ -18,6 +23,7 @@ 'CircuitPython') raise + class OtGPIO: """OpenTitan GPIO interface with an Adafruit NeoTrellis M4 Express. @@ -25,7 +31,7 @@ class OtGPIO: """ GPO_ON = (20, 0, 0) # red - GPO_OFF = (0, 20, 0) # green + GPO_OFF = (0, 20, 0) # green GPI_ON = (0, 0, 80) # bright blue GPI_OFF = (2, 2, 2) # greyish @@ -42,7 +48,7 @@ def __init__(self, serial): self._lock_in = 0 # locked keys self._lock_time = {} # when key has been first pressed (ns timestamp) - def _update_input(self, newval, force=False): + def _update_input(self, newval): ts = now() change = self._kin ^ newval self._kin = newval diff --git a/scripts/opentitan/uartmux.py b/scripts/opentitan/uartmux.py new file mode 100755 index 000000000000..c6dfc27ae284 --- /dev/null +++ b/scripts/opentitan/uartmux.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023-2024 Rivos, Inc. +# SPDX-License-Identifier: Apache2 + +"""QEMU UART muxer. + + :author: Emmanuel Blot +""" + +from argparse import ArgumentParser +from collections import deque +from logging import getLogger +from socketserver import StreamRequestHandler, ThreadingTCPServer +from sys import exit as sysexit, modules, stderr, stdout +from threading import Event, Lock, Thread +from traceback import format_exc +from typing import Deque, List, Optional, Set, TextIO, Tuple + +from ot.util.log import configure_loggers + + +class UartHandler(StreamRequestHandler): + """Handle a single QEMU output stream. + """ + + def __init__(self, *args, **kwargs): + self._buffer = bytearray() + self._id = - 1 + self._log = None + # init calls handle immediately, so local attributes need to be + # initialized first + super().__init__(*args, **kwargs) + + def setup(self): + self._id = self.server.get_id(self) + self._log = getLogger(f'mux.h[{self._id}]') + self._log.debug('connected') + self.request.settimeout(0.2) + + def finish(self): + self._log.debug('disconnected') + self.server.discard(self) + + def handle(self): + self._log.debug('handle') + try: + while self.server.resume: + try: + rdata = self.request.recv(1024) + except TimeoutError: + continue + except ConnectionResetError: + break + if not rdata: + # blocking socket reading nothing: client is disconnected + break + self._buffer.extend(rdata) + while self._buffer: + self._log.debug('buf: %d', len(self._buffer)) + pos = self._buffer.find(b'\n') + self._log.debug('pos %d', pos) + if pos < 0: + break + line = bytes(self._buffer[:pos+1]) + self._buffer[:] = self._buffer[pos+1:] + self.server.push(self._id, line) + except Exception as exc: + if self.server.debug: + print(format_exc(chain=False), file=stderr) + else: + self._log.critical('Error: %s', str(exc)) + self.server.resume = False + raise + + +class UartMuxer(ThreadingTCPServer): + """A simple UART muxer for multiple QEMU output streams + """ + + # do not wait for thread completion + daemon_threads = True + allow_reuse_address = True + timeout = None + + COLOR_PREFIX = '\x1b[' + COLOR_SUFFIX = ';1m' + RESET = '\x1b[0m' + + def __init__(self, addr: Tuple[str, int], out: TextIO, debug: bool = False, + separator: Optional[str] = None): + super().__init__(addr, UartHandler) + self._out = out + self._debug = debug + self._log = getLogger('mux.muxer') + self._runner = Thread(target=self._pop, daemon=True) + self._resume = False + self._que: Deque[Tuple[int, bytes]] = deque() + self._evt = Event() + self._lock = Lock() + self._handlers: List[UartHandler] = [] + self._discarded: Set[UartHandler] = set() + self._channel_count = 1 + self._channels: List[str] = [] + self._use_color = out.isatty() + if separator: + sep = separator if ' ' in separator else (separator * 80)[:80] + self._sep = f'{sep}\n' + else: + self._sep = None + + @property + def debug(self) -> bool: + """Tell whether mode is enabled.""" + return self._debug + + @property + def resume(self): + """Tell whether muxer should continue listening on.""" + return self._resume + + @resume.setter + def resume(self, value: bool): + value = bool(value) + if self._resume and not value: + self._resume = value + self._evt.set() + self.shutdown() + else: + self._resume = value + + def run(self, channel_count: int, channels: List[str]) -> None: + """Start listening on QEMU streams.""" + self._channel_count = min(channel_count, 8) + self._channels = channels + self._resume = True + self._runner.start() + try: + self.serve_forever() + finally: + if self._use_color: + self._out.write(self.RESET) + + def push(self, uart_id: int, line: bytes) -> None: + """Push a new log message line from one of the QEMU stream listeners.""" + self._que.append((uart_id, line)) + self._evt.set() + + def get_id(self, uart_handler: UartHandler) -> None: + """Get/assign a unique identifier to a listener.""" + with self._lock: + if self._sep and not self._handlers: + self._out.write(self._sep) + if uart_handler not in self._handlers: + self._handlers.append(uart_handler) + return self._handlers.index(uart_handler) + + def discard(self, uart_handler: UartHandler) -> None: + """Called when a listener terminates.""" + with self._lock: + try: + self._discarded.add(uart_handler) + except ValueError: + pass + # track listeners; when all known ones are closed it is likely the + # QEMU VM has quit, reset the all listeners so on next QEMU run, + # same ids are assigned (which is likely to assign the same color + # for the same QEMU output stream, despite it is somewhat a + # heuristic) + if self._discarded == set(self._handlers): + self._discarded.clear() + self._handlers.clear() + self._log.debug('All clients flushed') + + def _pop(self) -> None: + try: + while self._resume: + if not self._que: + if not self._evt.wait(0.1): + continue + self._evt.clear() + if self._resume and self._que: + uid, byteline = self._que.popleft() + line = byteline.decode(errors='ignore') + if uid < len(self._channels): + name = f'{self._channels[uid]}: ' + else: + name = '' + if self._use_color: + clr = uid % self._channel_count + 31 + ansi = f'{self.COLOR_PREFIX}{clr:d}{self.COLOR_SUFFIX}' + # self._log.error('ANSI %s', ansi) + self._out.write(f'{name}{ansi}{line}{self.RESET}') + # raise ValueError() + else: + self._out.write(line) + finally: + self.resume = False + + +def main(): + """Main routine""" + debug = True + default_port = 9000 + default_iface = 'localhost' + default_channel_count = 3 + mux = None + try: + desc = modules[__name__].__doc__.split('.', 1)[0].strip() + argparser = ArgumentParser(description=f'{desc}.') + argparser.add_argument('name', nargs='*', + help='assign name to input connection') + argparser.add_argument('-i', '--iface', default=default_iface, + help=f'specify TCP interface to listen to ' + f'(default: {default_iface})') + argparser.add_argument('-p', '--port', default=default_port, + help=f'specify TCP port to listen to ' + f'(default: {default_port})') + argparser.add_argument('-c', '--channel', + help=f'expected comm channel count' + f'(default: {default_channel_count})') + argparser.add_argument('-s', '--separator', + help='repeat separator between each session') + argparser.add_argument('-v', '--verbose', action='count', + help='increase verbosity') + argparser.add_argument('-d', '--debug', action='store_true', + help='enable debug mode') + args = argparser.parse_args() + debug = args.debug + + configure_loggers(args.verbose, 'mux') + + ThreadingTCPServer.allow_reuse_address = True + mux = UartMuxer((args.iface, args.port), stdout, debug, args.separator) + channel = args.channel + if channel is None: + channel = len(args.name) if args.name else default_channel_count + mux.run(channel, args.name) + + except (IOError, ValueError, ImportError) as exc: + print(f'\nError: {exc}', file=stderr) + if debug: + print(format_exc(chain=False), file=stderr) + sysexit(1) + except KeyboardInterrupt: + if mux: + mux.resume = False + sysexit(2) + + +if __name__ == '__main__': + main()