Skip to content

Commit

Permalink
[pwrmgr] Insert Interlock between External SoC Reset and Pwrmgr FSM
Browse files Browse the repository at this point in the history
1. Internally generated reset request passed to SoC.
2. Create a sticky assertion internally to log request.
   Sticky flag cleared only upon external reset deassertion
3. SoC transfer this request to platform to assert external reset
4. External SoC reset deasserts after some time
5. Pwrmgr stays in FastPwrStateRstWait state until the external SoC reset deasserts.
6. Boot / reset sequence continues
7. Also fixes the external reset signal glitch filter to use the por reset,
   This is required to make sure that the external reset state does not
   self-reset once asserted & faithfully forwards that state to pwrmgr
8. Added some debug visibility signals for pwrmgr
9. Added temporary reset loop back path in pwrmgr tb to
   translate internal reset req from OT --> ext reset from SoC to OT.
   Needs a proper fix in testbench
[extrst] Fixed chiplevel template for external reset loopback
[extrst] added parameter for halt on reset;
         Enables Earlgrey pwrmgr fsm to not wait for external reset

Signed-off-by: Neeraj Upasani <[email protected]>
  • Loading branch information
Neeraj Upasani committed Apr 16, 2024
1 parent e65178a commit a9c7ca9
Show file tree
Hide file tree
Showing 25 changed files with 389 additions and 64 deletions.
14 changes: 14 additions & 0 deletions hw/ip/pwrmgr/data/pwrmgr.hjson.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@
],

inter_signal_list: [
{ struct: "pwr_boot_status",
type: "uni",
name: "boot_status",
act: "req",
package: "pwrmgr_pkg",
},
{ struct: "pwr_ast",
type: "req_rsp",
name: "pwr_ast",
Expand Down Expand Up @@ -223,6 +229,14 @@

% endfor

{ name: "PwrFsmWait4ExtRst",
desc: "Number of reset requets",
type: "int",
default: "0",
local: "false",
expose: "true"
},

{ name: "NumRstReqs",
desc: "Number of peripheral reset requets",
type: "int",
Expand Down
4 changes: 3 additions & 1 deletion hw/ip/pwrmgr/dv/tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module tb;
wire clk_slow, rst_slow_n;
wire devmode;
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
wire int_reset_req;

// interfaces
clk_rst_if clk_rst_if (
Expand Down Expand Up @@ -49,6 +50,7 @@ module tb;
);

assign interrupts[0] = pwrmgr_if.intr_wakeup;
assign int_reset_req = tb.dut.internal_reset_req ;

pwrmgr_if pwrmgr_if (
.clk,
Expand Down Expand Up @@ -97,7 +99,7 @@ module tb;

.fetch_en_o(pwrmgr_if.fetch_en),
.wakeups_i (pwrmgr_if.wakeups_i),
.rstreqs_i (pwrmgr_if.rstreqs_i),
.rstreqs_i ({int_reset_req,pwrmgr_if.rstreqs_i[0]}),
.ndmreset_req_i(pwrmgr_if.cpu_i.ndmreset_req),

.lc_dft_en_i (pwrmgr_if.lc_dft_en),
Expand Down
1 change: 1 addition & 0 deletions hw/ip/pwrmgr/pwrmgr_pkg.core
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ filesets:
files_rtl:
depend:
- lowrisc:ip:pwrmgr_reg
- lowrisc:ip:rom_ctrl_pkg
files:
- rtl/pwrmgr_pkg.sv
file_type: systemVerilogSource
Expand Down
48 changes: 42 additions & 6 deletions hw/ip/pwrmgr/rtl/pwrmgr.sv
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ module pwrmgr
import pwrmgr_pkg::*;
import pwrmgr_reg_pkg::*;
#(
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},
parameter bit PwrFsmWait4ExtRst = 0
) (
// Clocks and resets
input clk_slow_i,
Expand Down Expand Up @@ -59,12 +60,13 @@ module pwrmgr
input pwr_cpu_t pwr_cpu_i,
// SEC_CM: LC_CTRL.INTERSIG.MUBI
output lc_ctrl_pkg::lc_tx_t fetch_en_o,
input lc_ctrl_pkg::lc_tx_t lc_hw_debug_en_i,
input lc_ctrl_pkg::lc_tx_t lc_dft_en_i,
input lc_ctrl_pkg::lc_tx_t lc_hw_debug_en_i,
input lc_ctrl_pkg::lc_tx_t lc_dft_en_i,

output pwr_boot_status_t boot_status_o,
// peripherals wakeup and reset requests
input [NumWkups-1:0] wakeups_i,
input [NumRstReqs-1:0] rstreqs_i,
input [NumWkups-1:0] wakeups_i,
input [NumRstReqs-1:0] rstreqs_i,

// cpu related inputs
input ndmreset_req_i,
Expand All @@ -88,6 +90,11 @@ module pwrmgr
output intr_wakeup_o

);

logic internal_reset_req;
logic strap_sampled;
logic ext_reset_req;

////////////////////////////////////////////////////
// Input handling //
////////////////////////////////////////////////////
Expand Down Expand Up @@ -504,6 +511,20 @@ module pwrmgr
{NumIntRstReqs{1'b1}},
slow_reset_en};

assign internal_reset_req =|(
slow_peri_reqs.rstreqs &
{{NumSwRstReq{1'b1}}, // SW driven reset
{NumDebugRstReqs{1'b1}}, // debugger reset
{NumIntRstReqs{1'b1}}, // {ESC reset, slow_fsm}
// exclude the external async reset
{1'b0,slow_reset_en[0]}
}
);

// bit1 is ext rst Do not mask.
// Always want to propagate to clear Reset Wait state in fast FSM
assign ext_reset_req = slow_peri_reqs.rstreqs[NumRstReqs-1] ;

for (genvar i = 0; i < NumWkups; i++) begin : gen_wakeup_status
assign hw2reg.wake_status[i].de = 1'b1;
assign hw2reg.wake_status[i].d = peri_reqs_masked.wakeups[i];
Expand Down Expand Up @@ -574,7 +595,9 @@ module pwrmgr

assign low_power_hint = reg2hw.control.low_power_hint.q == LowPower;

pwrmgr_fsm u_fsm (
pwrmgr_fsm #(
.PwrFsmWait4ExtRst(PwrFsmWait4ExtRst)
) u_fsm (
.clk_i,
.rst_ni,
.clk_slow_i,
Expand Down Expand Up @@ -602,6 +625,8 @@ module pwrmgr
.fall_through_o (low_power_fall_through),
.abort_o (low_power_abort),
.clr_hint_o (clr_hint),
.light_rst_req_i (internal_reset_req),
.ext_reset_req_i (ext_reset_req),

// rstmgr
.pwr_rst_o (pwr_rst_o),
Expand Down Expand Up @@ -635,6 +660,7 @@ module pwrmgr

// pinmux and other peripherals
.strap_o,
.strap_sampled_o (strap_sampled), // to debug monitoring logic
.low_power_o
);

Expand Down Expand Up @@ -685,6 +711,16 @@ module pwrmgr
.intr_o (intr_wakeup_o)
);

////////////////////////////////////////////////////
// Routing sstaus signal outputs for monitoring
////////////////////////////////////////////////////
assign boot_status_o.cpu_fetch_en = fetch_en_o;
assign boot_status_o.rom_ctrl_status = rom_ctrl_i;
assign boot_status_o.lc_done = pwr_lc_i.lc_done;
assign boot_status_o.otp_done = otp_rsp.otp_done;
assign boot_status_o.clk_status = pwr_clk_i;
assign boot_status_o.light_reset_req = internal_reset_req;
assign boot_status_o.strapSampled = strap_sampled;

////////////////////////////
/// Assertions
Expand Down
55 changes: 48 additions & 7 deletions hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@

`include "prim_assert.sv"

module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
module pwrmgr_fsm
import pwrmgr_pkg::*;
import pwrmgr_reg_pkg::*;
#(
parameter bit PwrFsmWait4ExtRst = 0
) (
input clk_i,
input rst_ni,
input clk_slow_i,
Expand All @@ -33,6 +38,9 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
output logic abort_o,
output logic clr_hint_o,
output logic clr_cfg_lock_o,
input logic light_rst_req_i, // internally generated reset request.
// Send to platform to assert reset
input logic ext_reset_req_i, // Internal Req held until ext reset deasserts

// rstmgr
output pwr_rst_req_t pwr_rst_o,
Expand Down Expand Up @@ -63,6 +71,7 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(

// pinmux
output logic strap_o,
output logic strap_sampled_o,
output logic low_power_o,

// processing elements
Expand Down Expand Up @@ -103,7 +112,7 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(

// strap sample should only happen on cold boot or when the
// the system goes through a reset cycle
logic strap_sampled;
// [output] logic strap_sampled;

// disable processing element fetching
lc_ctrl_pkg::lc_tx_t fetch_en_q, fetch_en_d;
Expand All @@ -118,6 +127,8 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
logic otp_init;
logic lc_init;
logic low_power_q, low_power_d;
logic ext_rst_req_d, ext_rst_req_q;
logic light_rst_req_q;

assign pd_n_rsts_asserted = pwr_rst_i.rst_lc_src_n[PowerDomains-1:OffDomainSelStart] == '0 &
pwr_rst_i.rst_sys_src_n[PowerDomains-1:OffDomainSelStart] == '0;
Expand Down Expand Up @@ -153,6 +164,33 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
assign reset_valid = reset_cause_q == LowPwrEntry ? main_pd_ni | pd_n_rsts_asserted :
reset_cause_q == HwReq ? all_rsts_asserted : 1'b0;


if (PwrFsmWait4ExtRst) begin : gen_wait2ext_rst

assign ext_rst_req_d = ext_reset_req_i;

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
light_rst_req_q <= 0;
ext_rst_req_q <= 0;
end else begin
ext_rst_req_q <= ext_rst_req_d;
if(light_rst_req_q && !ext_rst_req_d && ext_rst_req_q) begin
light_rst_req_q <= '0;
end else if (light_rst_req_i) begin
light_rst_req_q <= 1'b1;
end
end
end
end : gen_wait2ext_rst
else
begin : gen_no_wait2ext_rst
assign light_rst_req_q = 0;
assign ext_rst_req_q = 0;
assign ext_rst_req_d = 0;
end : gen_no_wait2ext_rst


always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_pwrup_q <= 1'b0;
Expand Down Expand Up @@ -180,11 +218,11 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
strap_sampled <= 1'b0;
strap_sampled_o <= 1'b0;
end else if (&rst_sys_req_q) begin
strap_sampled <= 1'b0;
strap_sampled_o <= 1'b0;
end else if (strap_o) begin
strap_sampled <= 1'b1;
strap_sampled_o <= 1'b1;
end
end

Expand Down Expand Up @@ -338,7 +376,7 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
end

FastPwrStateStrap: begin
strap_o = ~strap_sampled;
strap_o = ~strap_sampled_o;
state_d = FastPwrStateRomCheckDone;
end

Expand Down Expand Up @@ -471,7 +509,10 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
// cleared before proceeding. This also implies if the system is under a persistent
// glitch, or if someone just turned off the power before pwrmgr turns it off itself,
// we will stay stuck here and perpetually hold the system in reset.
if (reset_valid && !reset_reqs_i[ResetMainPwrIdx]) begin
// NumRstReqs-1 is the External SoC reset request.
// Need to hold in reset until external reset deasserts (i.e. light_rst_req_q goes low)
if (reset_valid && !reset_reqs_i[ResetMainPwrIdx]
&& !light_rst_req_q ) begin
state_d = FastPwrStateLowPower;
end
end
Expand Down
10 changes: 10 additions & 0 deletions hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ package pwrmgr_pkg;
logic ndmreset_req;
} pwrmgr_cpu_t;

typedef struct packed {
lc_ctrl_pkg::lc_tx_t cpu_fetch_en;
rom_ctrl_pkg::pwrmgr_data_t [pwrmgr_reg_pkg::NumRomInputs-1:0] rom_ctrl_status;
logic lc_done;
logic otp_done;
logic strapSampled;
logic light_reset_req;
pwr_clk_rsp_t clk_status;
} pwr_boot_status_t;

// exported resets

// default value for pwrmgr_ast_rsp_t (for dangling ports)
Expand Down
1 change: 1 addition & 0 deletions hw/ip/rstmgr/rstmgr_pkg.core
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ filesets:
files_rtl:
depend:
- lowrisc:ip:alert_handler_component
- lowrisc:ip:rom_ctrl_pkg
- lowrisc:ip:pwrmgr_pkg
- lowrisc:ip:rstmgr_reg
- "fileset_top ? (lowrisc:systems:rstmgr_pkg)"
Expand Down
Loading

0 comments on commit a9c7ca9

Please sign in to comment.