Skip to content

Commit 85a85e5

Browse files
committed
[ot] hw/opentitan: ot_flash: Add prog fifo, watermarks and fifo fixes
This commit introduces the `prog_fifo` counterpart to the existing `rd_fifo`, and adds additional functionality relating to the two FIFOs, whilst fixing some existing issues. This includes properly resetting related status and interrupt state values when FIFOs are reset. Basic functionality for writing to the prog FIFO is added, though the corresponding program operation is not yet implemented. Watermarks have been added via the use of the FIFO_LVL register, and these are hooked up to the corresponding interrupts. Signed-off-by: Alex Jones <[email protected]>
1 parent 0880f1a commit 85a85e5

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

hw/opentitan/ot_flash.c

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ enum {
686686
#define OP_INIT_DURATION_NS 1000000u /* 1 ms */
687687
#define ELFNAME_SIZE 256u
688688
#define OT_FLASH_READ_FIFO_SIZE 16u
689+
#define OT_FLASH_PROG_FIFO_SIZE 16u
689690
#define BUS_PGM_RES ((REG_BUS_PGM_RES_BYTES) / (OT_TL_UL_D_WIDTH_BYTES))
690691

691692
typedef struct {
@@ -748,6 +749,7 @@ struct OtFlashState {
748749
bool erase_sel;
749750
} op;
750751
OtFifo32 rd_fifo;
752+
OtFifo32 prog_fifo;
751753
OtFlashStorage flash;
752754

753755
BlockBackend *blk; /* Flash backend */
@@ -781,6 +783,42 @@ static bool ot_flash_regs_is_wr_enabled(OtFlashState *s, unsigned regwen)
781783
return (bool)(s->regs[regwen] & REGWEN_EN_MASK);
782784
}
783785

786+
static void ot_flash_update_rd_watermark(OtFlashState *s)
787+
{
788+
unsigned rd_watermark_level =
789+
SHARED_FIELD_EX32(s->regs[R_FIFO_LVL], FIFO_LVL_RD);
790+
unsigned lvl = ot_fifo32_num_used(&s->rd_fifo);
791+
792+
/* Read FIFO watermark generates an interrupt when the Read FIFO fills to
793+
(equal to or greater than) the watermark level. */
794+
if (lvl >= rd_watermark_level) {
795+
s->regs[R_INTR_STATE] |= INTR_RD_LVL_MASK;
796+
} else {
797+
s->regs[R_INTR_STATE] &= ~INTR_RD_LVL_MASK;
798+
}
799+
trace_ot_flash_update_rd_watermark(lvl, rd_watermark_level);
800+
ot_flash_update_irqs(s);
801+
}
802+
803+
static void ot_flash_update_prog_watermark(OtFlashState *s)
804+
{
805+
unsigned prog_watermark_level =
806+
SHARED_FIELD_EX32(s->regs[R_FIFO_LVL], FIFO_LVL_PROG);
807+
unsigned lvl = ot_fifo32_num_used(&s->prog_fifo);
808+
809+
/* Prog FIFO watermark generates an interrupt when the Prog FIFO drains to
810+
(equal to or less than) the watermark level. */
811+
if (lvl <= prog_watermark_level) {
812+
s->regs[R_INTR_STATE] |= INTR_PROG_LVL_MASK;
813+
} else {
814+
s->regs[R_INTR_STATE] &= ~INTR_PROG_LVL_MASK;
815+
}
816+
trace_ot_flash_update_prog_watermark(lvl, prog_watermark_level);
817+
ot_flash_update_irqs(s);
818+
}
819+
820+
821+
784822
static void ot_flash_op_signal(void *opaque)
785823
{
786824
OtFlashState *s = opaque;
@@ -825,6 +863,26 @@ static bool ot_flash_fifo_in_reset(OtFlashState *s)
825863
return (bool)s->regs[R_FIFO_RST];
826864
}
827865

866+
static void ot_flash_reset_rd_fifo(OtFlashState *s)
867+
{
868+
ot_fifo32_reset(&s->rd_fifo);
869+
s->regs[R_STATUS] |= R_STATUS_RD_EMPTY_MASK;
870+
s->regs[R_STATUS] &= ~R_STATUS_RD_FULL_MASK;
871+
s->regs[R_INTR_STATE] &= ~INTR_RD_FULL_MASK;
872+
trace_ot_flash_reset_fifo("rd");
873+
ot_flash_update_rd_watermark(s);
874+
}
875+
876+
static void ot_flash_reset_prog_fifo(OtFlashState *s)
877+
{
878+
ot_fifo32_reset(&s->prog_fifo);
879+
s->regs[R_STATUS] |= R_STATUS_PROG_EMPTY_MASK;
880+
s->regs[R_STATUS] &= ~R_STATUS_PROG_FULL_MASK;
881+
s->regs[R_INTR_STATE] |= INTR_PROG_EMPTY_MASK;
882+
trace_ot_flash_reset_fifo("prog");
883+
ot_flash_update_prog_watermark(s);
884+
}
885+
828886
static void ot_flash_set_error(OtFlashState *s, uint32_t ebit, uint32_t eaddr)
829887
{
830888
if (ebit) {
@@ -921,6 +979,7 @@ static void ot_flash_op_read(OtFlashState *s)
921979
if (!ot_flash_fifo_in_reset(s)) {
922980
ot_fifo32_push(&s->rd_fifo, word);
923981
s->regs[R_STATUS] &= ~R_STATUS_RD_EMPTY_MASK;
982+
ot_flash_update_rd_watermark(s);
924983
}
925984
if (ot_fifo32_is_full(&s->rd_fifo)) {
926985
s->regs[R_STATUS] |= R_STATUS_RD_FULL_MASK;
@@ -1105,6 +1164,10 @@ static uint64_t ot_flash_regs_read(void *opaque, hwaddr addr, unsigned size)
11051164
(uint32_t)ot_fifo32_is_full(&s->rd_fifo));
11061165
val32 = FIELD_DP32(val32, STATUS, RD_EMPTY,
11071166
(uint32_t)ot_fifo32_is_empty(&s->rd_fifo));
1167+
val32 = FIELD_DP32(val32, STATUS, PROG_FULL,
1168+
(uint32_t)ot_fifo32_is_full(&s->prog_fifo));
1169+
val32 = FIELD_DP32(val32, STATUS, PROG_EMPTY,
1170+
(uint32_t)ot_fifo32_is_empty(&s->prog_fifo));
11081171
break;
11091172
case R_RD_FIFO:
11101173
if (!ot_fifo32_is_empty(&s->rd_fifo)) {
@@ -1114,6 +1177,7 @@ static uint64_t ot_flash_regs_read(void *opaque, hwaddr addr, unsigned size)
11141177
if (ot_fifo32_is_empty(&s->rd_fifo)) {
11151178
s->regs[R_STATUS] |= R_STATUS_RD_EMPTY_MASK;
11161179
}
1180+
ot_flash_update_rd_watermark(s);
11171181
ot_flash_update_irqs(s);
11181182
if (s->op.count) {
11191183
ot_flash_op_execute(s);
@@ -1124,7 +1188,10 @@ static uint64_t ot_flash_regs_read(void *opaque, hwaddr addr, unsigned size)
11241188
}
11251189
break;
11261190
case R_CURR_FIFO_LVL:
1127-
val32 = ot_fifo32_num_used(&s->rd_fifo) << FIFO_LVL_RD_SHIFT;
1191+
val32 =
1192+
SHARED_FIELD_DP32(0u, FIFO_LVL_RD, ot_fifo32_num_used(&s->rd_fifo));
1193+
val32 = SHARED_FIELD_DP32(val32, FIFO_LVL_PROG,
1194+
ot_fifo32_num_used(&s->prog_fifo));
11281195
break;
11291196
case R_ALERT_TEST:
11301197
case R_PROG_FIFO:
@@ -1455,14 +1522,35 @@ static void ot_flash_regs_write(void *opaque, hwaddr addr, uint64_t val64,
14551522
case R_FIFO_LVL:
14561523
val32 &= FIFO_LVL_PROG_MASK | FIFO_LVL_RD_MASK;
14571524
s->regs[reg] = val32;
1525+
ot_flash_update_rd_watermark(s);
1526+
ot_flash_update_prog_watermark(s);
14581527
break;
14591528
case R_FIFO_RST:
14601529
val32 &= R_FIFO_RST_EN_MASK;
14611530
s->regs[reg] = val32;
14621531
if (val32) {
1463-
ot_fifo32_reset(&s->rd_fifo);
1532+
ot_flash_reset_rd_fifo(s);
1533+
ot_flash_reset_prog_fifo(s);
14641534
}
1535+
break;
14651536
case R_PROG_FIFO:
1537+
if (!ot_fifo32_is_full(&s->prog_fifo)) {
1538+
if (!ot_flash_fifo_in_reset(s)) {
1539+
ot_fifo32_push(&s->prog_fifo, val32);
1540+
s->regs[R_STATUS] &= ~R_STATUS_PROG_EMPTY_MASK;
1541+
s->regs[R_INTR_STATE] &= ~INTR_PROG_EMPTY_MASK;
1542+
ot_flash_update_prog_watermark(s);
1543+
ot_flash_update_irqs(s);
1544+
}
1545+
if (ot_fifo32_is_full(&s->prog_fifo)) {
1546+
s->regs[R_STATUS] |= R_STATUS_PROG_FULL_MASK;
1547+
}
1548+
if (s->op.count) {
1549+
ot_flash_op_execute(s);
1550+
}
1551+
} else {
1552+
qemu_log_mask(LOG_GUEST_ERROR, "%s: Write full FIFO\n", __func__);
1553+
}
14661554
break;
14671555
case R_FAULT_STATUS: {
14681556
uint32_t rw0c_mask = (R_FAULT_STATUS_PHY_RELBL_ERR_MASK |
@@ -1748,7 +1836,8 @@ static void ot_flash_reset(DeviceState *dev)
17481836
ot_flash_update_irqs(s);
17491837
ot_flash_update_alerts(s);
17501838

1751-
ot_fifo32_reset(&s->rd_fifo);
1839+
ot_flash_reset_rd_fifo(s);
1840+
ot_flash_reset_prog_fifo(s);
17521841
}
17531842

17541843
#ifdef USE_HEXDUMP
@@ -2023,6 +2112,7 @@ static void ot_flash_init(Object *obj)
20232112
s->regs = g_new0(uint32_t, REGS_COUNT);
20242113
s->csrs = g_new0(uint32_t, CSRS_COUNT);
20252114
ot_fifo32_create(&s->rd_fifo, OT_FLASH_READ_FIFO_SIZE);
2115+
ot_fifo32_create(&s->prog_fifo, OT_FLASH_PROG_FIFO_SIZE);
20262116

20272117
for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) {
20282118
ibex_sysbus_init_irq(obj, &s->irqs[ix]);

hw/opentitan/trace-events

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ ot_flash_mem_read_out(uint32_t addr, unsigned size, uint32_t val, uint32_t pc) "
185185
ot_flash_op_complete(const char *op, bool success) "%s: %u"
186186
ot_flash_op_start(const char *op) "%s"
187187
ot_flash_set_error(const char *op, uint32_t err_code, uint32_t err_addr) "%s: err=%08x at addr=0x%06x"
188+
ot_flash_update_rd_watermark(unsigned val, unsigned watermark) "%u >= %u"
189+
ot_flash_update_prog_watermark(unsigned val, unsigned watermark) "%u <= %u"
190+
ot_flash_reset_fifo(const char *name) "%s"
188191

189192
# ot_gpio.c
190193

0 commit comments

Comments
 (0)