[flash_ctrl] Properly error bus access during disable
- fixes #14616
- previously, when flash was disabled, an access to the program
read fifos would hang.
- this update makes it so the accesses error back properly.
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index 333ffa4..30d9ae9 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -112,6 +112,7 @@
logic intg_err;
logic eflash_cmd_intg_err;
logic tl_gate_intg_err;
+ logic tl_prog_gate_intg_err;
// SEC_CM: REG.BUS.INTEGRITY
// SEC_CM: CTRL.CONFIG.REGWEN
@@ -500,6 +501,23 @@
// strategy has been identified
assign prog_op_valid = op_start & prog_op;
+ tlul_pkg::tl_h2d_t prog_tl_h2d;
+ tlul_pkg::tl_d2h_t prog_tl_d2h;
+
+ // the program path also needs an lc gate to error back when flash is disabled.
+ // This is because tlul_adapter_sram does not actually have a way of signaling
+ // write errors, only read errors.
+ tlul_lc_gate u_prog_tl_gate (
+ .clk_i,
+ .rst_ni,
+ .tl_h2d_i(tl_win_h2d[0]),
+ .tl_d2h_o(tl_win_d2h[0]),
+ .tl_h2d_o(prog_tl_h2d),
+ .tl_d2h_i(prog_tl_d2h),
+ .lc_en_i(lc_ctrl_pkg::mubi4_to_lc_inv(flash_disable[ProgFifoIdx])),
+ .err_o(tl_prog_gate_intg_err)
+ );
+
tlul_adapter_sram #(
.SramAw(1), //address unused
.SramDw(BusWidth),
@@ -509,8 +527,8 @@
) u_to_prog_fifo (
.clk_i,
.rst_ni,
- .tl_i (tl_win_h2d[0]),
- .tl_o (tl_win_d2h[0]),
+ .tl_i (prog_tl_h2d),
+ .tl_o (prog_tl_d2h),
.en_ifetch_i (prim_mubi_pkg::MuBi4False),
.req_o (sw_wvalid),
.req_type_o (),
@@ -595,9 +613,10 @@
assign sw_rd_op = reg2hw.control.start.q & (reg2hw.control.op.q == FlashOpRead);
// If software ever attempts to read when the FIFO is empty AND if it has never
- // initiated a transaction, then it is a read that can never complete, error
- // back immediately.
- assign rd_no_op_d = adapter_req & ~sw_rd_op & ~sw_rfifo_rvalid;
+ // initiated a transaction, OR when flash is disabled, then it is a read that
+ // can never complete, error back immediately.
+ assign rd_no_op_d = adapter_req & ((~sw_rd_op & ~sw_rfifo_rvalid) |
+ (prim_mubi_pkg::mubi4_test_true_loose(flash_disable[RdFifoIdx])));
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@@ -1071,7 +1090,7 @@
assign hw2reg.std_fault_status.ctrl_cnt_err.d = 1'b1;
assign hw2reg.std_fault_status.fifo_err.d = 1'b1;
assign hw2reg.std_fault_status.reg_intg_err.de = intg_err | eflash_cmd_intg_err |
- tl_gate_intg_err;
+ tl_gate_intg_err | tl_prog_gate_intg_err;
assign hw2reg.std_fault_status.prog_intg_err.de = flash_phy_rsp.prog_intg_err;
assign hw2reg.std_fault_status.lcmgr_err.de = lcmgr_err;
assign hw2reg.std_fault_status.lcmgr_intg_err.de = lcmgr_intg_err;
@@ -1395,6 +1414,8 @@
u_ctrl_arb.u_state_regs, alert_tx_o[1])
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlLcGateFsm_A,
u_tl_gate.u_state_regs, alert_tx_o[1])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlProgLcGateFsm_A,
+ u_prog_tl_gate.u_state_regs, alert_tx_o[1])
for (genvar i=0; i<NumBanks; i++) begin : gen_phy_assertions
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(PhyFsmCheck_A,
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
index 49b24d9..0a78e14 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
@@ -81,13 +81,15 @@
};
// Flash Disable usage
- typedef enum logic [2:0] {
+ typedef enum logic [3:0] {
PhyDisableIdx,
ArbFsmDisableIdx,
LcMgrDisableIdx,
MpDisableIdx,
HostDisableIdx,
IFetchDisableIdx,
+ RdFifoIdx,
+ ProgFifoIdx,
FlashDisableLast
} flash_disable_pos_e;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
index 71c7755..1fe9de2 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
@@ -112,6 +112,7 @@
logic intg_err;
logic eflash_cmd_intg_err;
logic tl_gate_intg_err;
+ logic tl_prog_gate_intg_err;
// SEC_CM: REG.BUS.INTEGRITY
// SEC_CM: CTRL.CONFIG.REGWEN
@@ -501,6 +502,23 @@
// strategy has been identified
assign prog_op_valid = op_start & prog_op;
+ tlul_pkg::tl_h2d_t prog_tl_h2d;
+ tlul_pkg::tl_d2h_t prog_tl_d2h;
+
+ // the program path also needs an lc gate to error back when flash is disabled.
+ // This is because tlul_adapter_sram does not actually have a way of signaling
+ // write errors, only read errors.
+ tlul_lc_gate u_prog_tl_gate (
+ .clk_i,
+ .rst_ni,
+ .tl_h2d_i(tl_win_h2d[0]),
+ .tl_d2h_o(tl_win_d2h[0]),
+ .tl_h2d_o(prog_tl_h2d),
+ .tl_d2h_i(prog_tl_d2h),
+ .lc_en_i(lc_ctrl_pkg::mubi4_to_lc_inv(flash_disable[ProgFifoIdx])),
+ .err_o(tl_prog_gate_intg_err)
+ );
+
tlul_adapter_sram #(
.SramAw(1), //address unused
.SramDw(BusWidth),
@@ -510,8 +528,8 @@
) u_to_prog_fifo (
.clk_i,
.rst_ni,
- .tl_i (tl_win_h2d[0]),
- .tl_o (tl_win_d2h[0]),
+ .tl_i (prog_tl_h2d),
+ .tl_o (prog_tl_d2h),
.en_ifetch_i (prim_mubi_pkg::MuBi4False),
.req_o (sw_wvalid),
.req_type_o (),
@@ -596,9 +614,10 @@
assign sw_rd_op = reg2hw.control.start.q & (reg2hw.control.op.q == FlashOpRead);
// If software ever attempts to read when the FIFO is empty AND if it has never
- // initiated a transaction, then it is a read that can never complete, error
- // back immediately.
- assign rd_no_op_d = adapter_req & ~sw_rd_op & ~sw_rfifo_rvalid;
+ // initiated a transaction, OR when flash is disabled, then it is a read that
+ // can never complete, error back immediately.
+ assign rd_no_op_d = adapter_req & ((~sw_rd_op & ~sw_rfifo_rvalid) |
+ (prim_mubi_pkg::mubi4_test_true_loose(flash_disable[RdFifoIdx])));
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@@ -1072,7 +1091,7 @@
assign hw2reg.std_fault_status.ctrl_cnt_err.d = 1'b1;
assign hw2reg.std_fault_status.fifo_err.d = 1'b1;
assign hw2reg.std_fault_status.reg_intg_err.de = intg_err | eflash_cmd_intg_err |
- tl_gate_intg_err;
+ tl_gate_intg_err | tl_prog_gate_intg_err;
assign hw2reg.std_fault_status.prog_intg_err.de = flash_phy_rsp.prog_intg_err;
assign hw2reg.std_fault_status.lcmgr_err.de = lcmgr_err;
assign hw2reg.std_fault_status.lcmgr_intg_err.de = lcmgr_intg_err;
@@ -1396,6 +1415,8 @@
u_ctrl_arb.u_state_regs, alert_tx_o[1])
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlLcGateFsm_A,
u_tl_gate.u_state_regs, alert_tx_o[1])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlProgLcGateFsm_A,
+ u_prog_tl_gate.u_state_regs, alert_tx_o[1])
for (genvar i=0; i<NumBanks; i++) begin : gen_phy_assertions
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(PhyFsmCheck_A,
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
index a958c90..605ca01 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
@@ -81,13 +81,15 @@
};
// Flash Disable usage
- typedef enum logic [2:0] {
+ typedef enum logic [3:0] {
PhyDisableIdx,
ArbFsmDisableIdx,
LcMgrDisableIdx,
MpDisableIdx,
HostDisableIdx,
IFetchDisableIdx,
+ RdFifoIdx,
+ ProgFifoIdx,
FlashDisableLast
} flash_disable_pos_e;
diff --git a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv
index ec13e01..92a48ff 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv
+++ b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv
@@ -118,6 +118,7 @@
logic intg_err;
logic eflash_cmd_intg_err;
logic tl_gate_intg_err;
+ logic tl_prog_gate_intg_err;
// SEC_CM: REG.BUS.INTEGRITY
// SEC_CM: CTRL.CONFIG.REGWEN
@@ -507,6 +508,23 @@
// strategy has been identified
assign prog_op_valid = op_start & prog_op;
+ tlul_pkg::tl_h2d_t prog_tl_h2d;
+ tlul_pkg::tl_d2h_t prog_tl_d2h;
+
+ // the program path also needs an lc gate to error back when flash is disabled.
+ // This is because tlul_adapter_sram does not actually have a way of signaling
+ // write errors, only read errors.
+ tlul_lc_gate u_prog_tl_gate (
+ .clk_i,
+ .rst_ni,
+ .tl_h2d_i(tl_win_h2d[0]),
+ .tl_d2h_o(tl_win_d2h[0]),
+ .tl_h2d_o(prog_tl_h2d),
+ .tl_d2h_i(prog_tl_d2h),
+ .lc_en_i(lc_ctrl_pkg::mubi4_to_lc_inv(flash_disable[ProgFifoIdx])),
+ .err_o(tl_prog_gate_intg_err)
+ );
+
tlul_adapter_sram #(
.SramAw(1), //address unused
.SramDw(BusWidth),
@@ -516,8 +534,8 @@
) u_to_prog_fifo (
.clk_i,
.rst_ni,
- .tl_i (tl_win_h2d[0]),
- .tl_o (tl_win_d2h[0]),
+ .tl_i (prog_tl_h2d),
+ .tl_o (prog_tl_d2h),
.en_ifetch_i (prim_mubi_pkg::MuBi4False),
.req_o (sw_wvalid),
.req_type_o (),
@@ -602,9 +620,10 @@
assign sw_rd_op = reg2hw.control.start.q & (reg2hw.control.op.q == FlashOpRead);
// If software ever attempts to read when the FIFO is empty AND if it has never
- // initiated a transaction, then it is a read that can never complete, error
- // back immediately.
- assign rd_no_op_d = adapter_req & ~sw_rd_op & ~sw_rfifo_rvalid;
+ // initiated a transaction, OR when flash is disabled, then it is a read that
+ // can never complete, error back immediately.
+ assign rd_no_op_d = adapter_req & ((~sw_rd_op & ~sw_rfifo_rvalid) |
+ (prim_mubi_pkg::mubi4_test_true_loose(flash_disable[RdFifoIdx])));
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@@ -1078,7 +1097,7 @@
assign hw2reg.std_fault_status.ctrl_cnt_err.d = 1'b1;
assign hw2reg.std_fault_status.fifo_err.d = 1'b1;
assign hw2reg.std_fault_status.reg_intg_err.de = intg_err | eflash_cmd_intg_err |
- tl_gate_intg_err;
+ tl_gate_intg_err | tl_prog_gate_intg_err;
assign hw2reg.std_fault_status.prog_intg_err.de = flash_phy_rsp.prog_intg_err;
assign hw2reg.std_fault_status.lcmgr_err.de = lcmgr_err;
assign hw2reg.std_fault_status.lcmgr_intg_err.de = lcmgr_intg_err;
@@ -1402,6 +1421,8 @@
u_ctrl_arb.u_state_regs, alert_tx_o[1])
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlLcGateFsm_A,
u_tl_gate.u_state_regs, alert_tx_o[1])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlProgLcGateFsm_A,
+ u_prog_tl_gate.u_state_regs, alert_tx_o[1])
for (genvar i=0; i<NumBanks; i++) begin : gen_phy_assertions
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(PhyFsmCheck_A,
diff --git a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv
index 14f9829..3b72a03 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv
+++ b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv
@@ -87,13 +87,15 @@
};
// Flash Disable usage
- typedef enum logic [2:0] {
+ typedef enum logic [3:0] {
PhyDisableIdx,
ArbFsmDisableIdx,
LcMgrDisableIdx,
MpDisableIdx,
HostDisableIdx,
IFetchDisableIdx,
+ RdFifoIdx,
+ ProgFifoIdx,
FlashDisableLast
} flash_disable_pos_e;