From b9a145496a129952e6e535dd5d601ff73fed8fd3 Mon Sep 17 00:00:00 2001 From: Michael Schaffner Date: Tue, 5 Mar 2024 13:14:19 -0800 Subject: [PATCH] [adc_ctrl] Updates to LP -> NP transition Signed-off-by: Michael Schaffner --- hw/ip/adc_ctrl/data/adc_ctrl.hjson | 71 +++++- hw/ip/adc_ctrl/doc/registers.md | 87 +++++-- hw/ip/adc_ctrl/rtl/adc_ctrl.sv | 5 +- hw/ip/adc_ctrl/rtl/adc_ctrl_core.sv | 30 ++- hw/ip/adc_ctrl/rtl/adc_ctrl_fsm.sv | 8 +- hw/ip/adc_ctrl/rtl/adc_ctrl_intr.sv | 81 +++--- hw/ip/adc_ctrl/rtl/adc_ctrl_reg_pkg.sv | 87 ++++--- hw/ip/adc_ctrl/rtl/adc_ctrl_reg_top.sv | 277 ++++++++++++++++----- sw/device/lib/dif/dif_adc_ctrl.c | 4 +- sw/device/lib/dif/dif_adc_ctrl.h | 6 +- sw/device/lib/dif/dif_adc_ctrl_unittest.cc | 24 +- 11 files changed, 508 insertions(+), 172 deletions(-) diff --git a/hw/ip/adc_ctrl/data/adc_ctrl.hjson b/hw/ip/adc_ctrl/data/adc_ctrl.hjson index 5e19824b384e99..f4551f06c233a7 100644 --- a/hw/ip/adc_ctrl/data/adc_ctrl.hjson +++ b/hw/ip/adc_ctrl/data/adc_ctrl.hjson @@ -306,8 +306,29 @@ resval: "0", fields: [ { bits: "NumAdcFilter-1:0", - name: "EN", - desc: "0: filter match wil not generate wakeupe; 1: filter match will generate wakeup", + name: "MATCH_EN", + desc: ''' + Filter wakeup source. + + 0: filter match will not generate wakeup; + 1: filter match will generate wakeup + ''' + } + { + bits: "NumAdcFilter:NumAdcFilter", + name: "TRANS_EN", + desc: ''' + Wakeup due to FSM transition from low power sampling + mode to normal sampling mode. + + Note that this wakeup source is primarily intended for debug purposes. + If enabled all the time, this can lead to many wakeups due to false + positives that are ruled out automatically by adc_ctrl after + transitioning from LP -> NP. + + 0: transition match will not generate wakeup; + 1: transition match will generate wakeup + ''' } ] } @@ -324,9 +345,13 @@ resval: "0", fields: [ { bits: "7:0", - name: "COND", + name: "MATCH", desc: "0: filter condition is not met; 1: filter condition is met", } + { bits: "NumAdcFilter:NumAdcFilter", + name: "TRANS", + desc: "0: transition did not occur; 1: transition occurred", + } ] } @@ -343,10 +368,36 @@ hwaccess: "hro", resval: "0", fields: [ - { bits: "8:0", - name: "EN", - desc: "0: interrupt source is not enabled; 1: interrupt source is enabled", + { bits: "NumAdcFilter-1:0", + name: "MATCH_EN", + desc: ''' + Filter interrupt source. + + 0: interrupt source is not enabled; 1: interrupt source is enabled + ''' + } + { + bits: "NumAdcFilter:NumAdcFilter", + name: "TRANS_EN", + desc: ''' + Interrupt due to FSM transition from low power sampling + mode to normal sampling mode. This is mainly intended for debug. + + Note that this interrupt is primarily intended for debug purposes. + + 0: interrupt source is not enabled; 1: interrupt source is enabled + ''' } + { + bits: "NumAdcFilter+1:NumAdcFilter+1", + name: "ONESHOT_EN", + desc: ''' + Interrupt due to oneshot sampling. + + 0: interrupt source is not enabled; 1: interrupt source is enabled + ''' + } + ] } @@ -360,11 +411,15 @@ "excl:CsrNonInitTests:CsrExclCheck"], fields: [ { bits: "NumAdcFilter-1:0", - name: "filter_match", + name: "MATCH", desc: "0: filter condition is not met; 1: filter condition is met", } { bits: "NumAdcFilter:NumAdcFilter", - name: "oneshot", + name: "TRANS", + desc: "0: transition did not occur; 1: transition occurred", + } + { bits: "NumAdcFilter+1:NumAdcFilter+1", + name: "ONESHOT", desc: "0: oneshot sample is not done ; 1: oneshot sample is done", } ] diff --git a/hw/ip/adc_ctrl/doc/registers.md b/hw/ip/adc_ctrl/doc/registers.md index 349ad3a77bdd24..d41b94b42549a4 100644 --- a/hw/ip/adc_ctrl/doc/registers.md +++ b/hw/ip/adc_ctrl/doc/registers.md @@ -304,18 +304,37 @@ ADC value sampled on channel Enable filter matches as wakeups - Offset: `0x6c` - Reset default: `0x0` -- Reset mask: `0xff` +- Reset mask: `0x1ff` ### Fields ```wavejson -{"reg": [{"name": "EN", "bits": 8, "attr": ["rw"], "rotate": 0}, {"bits": 24}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}} +{"reg": [{"name": "MATCH_EN", "bits": 8, "attr": ["rw"], "rotate": 0}, {"name": "TRANS_EN", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 100}} ``` -| Bits | Type | Reset | Name | Description | -|:------:|:------:|:-------:|:-------|:-------------------------------------------------------------------------------| -| 31:8 | | | | Reserved | -| 7:0 | rw | 0x0 | EN | 0: filter match wil not generate wakeupe; 1: filter match will generate wakeup | +| Bits | Type | Reset | Name | +|:------:|:------:|:-------:|:--------------------------------------| +| 31:9 | | | Reserved | +| 8 | rw | 0x0 | [TRANS_EN](#adc_wakeup_ctl--trans_en) | +| 7:0 | rw | 0x0 | [MATCH_EN](#adc_wakeup_ctl--match_en) | + +### adc_wakeup_ctl . TRANS_EN +Wakeup due to FSM transition from low power sampling +mode to normal sampling mode. + +Note that this wakeup source is primarily intended for debug purposes. +If enabled all the time, this can lead to many wakeups due to false +positives that are ruled out automatically by adc_ctrl after +transitioning from LP -> NP. + +0: transition match will not generate wakeup; +1: transition match will generate wakeup + +### adc_wakeup_ctl . MATCH_EN +Filter wakeup source. + +0: filter match will not generate wakeup; +1: filter match will generate wakeup ## filter_status Adc filter match status @@ -323,18 +342,19 @@ Adc filter match status Indicates whether a particular filter has matched on all channels. - Offset: `0x70` - Reset default: `0x0` -- Reset mask: `0xff` +- Reset mask: `0x1ff` ### Fields ```wavejson -{"reg": [{"name": "COND", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"bits": 24}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}} +{"reg": [{"name": "MATCH", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"name": "TRANS", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}} ``` | Bits | Type | Reset | Name | Description | |:------:|:------:|:-------:|:-------|:-----------------------------------------------------------| -| 31:8 | | | | Reserved | -| 7:0 | rw1c | 0x0 | COND | 0: filter condition is not met; 1: filter condition is met | +| 31:9 | | | | Reserved | +| 8 | rw1c | 0x0 | TRANS | 0: transition did not occur; 1: transition occurred | +| 7:0 | rw1c | 0x0 | MATCH | 0: filter condition is not met; 1: filter condition is met | ## adc_intr_ctl Interrupt enable controls. @@ -345,36 +365,57 @@ which internal sources are actually registered. This register uses the same bit enumeration as [`ADC_INTR_STATUS`](#adc_intr_status) - Offset: `0x74` - Reset default: `0x0` -- Reset mask: `0x1ff` +- Reset mask: `0x3ff` ### Fields ```wavejson -{"reg": [{"name": "EN", "bits": 9, "attr": ["rw"], "rotate": 0}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}} +{"reg": [{"name": "MATCH_EN", "bits": 8, "attr": ["rw"], "rotate": 0}, {"name": "TRANS_EN", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "ONESHOT_EN", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 22}], "config": {"lanes": 1, "fontsize": 10, "vspace": 120}} ``` -| Bits | Type | Reset | Name | Description | -|:------:|:------:|:-------:|:-------|:-------------------------------------------------------------------| -| 31:9 | | | | Reserved | -| 8:0 | rw | 0x0 | EN | 0: interrupt source is not enabled; 1: interrupt source is enabled | +| Bits | Type | Reset | Name | +|:------:|:------:|:-------:|:----------------------------------------| +| 31:10 | | | Reserved | +| 9 | rw | 0x0 | [ONESHOT_EN](#adc_intr_ctl--oneshot_en) | +| 8 | rw | 0x0 | [TRANS_EN](#adc_intr_ctl--trans_en) | +| 7:0 | rw | 0x0 | [MATCH_EN](#adc_intr_ctl--match_en) | + +### adc_intr_ctl . ONESHOT_EN +Interrupt due to oneshot sampling. + +0: interrupt source is not enabled; 1: interrupt source is enabled + +### adc_intr_ctl . TRANS_EN +Interrupt due to FSM transition from low power sampling +mode to normal sampling mode. This is mainly intended for debug. + +Note that this interrupt is primarily intended for debug purposes. + +0: interrupt source is not enabled; 1: interrupt source is enabled + +### adc_intr_ctl . MATCH_EN +Filter interrupt source. + +0: interrupt source is not enabled; 1: interrupt source is enabled ## adc_intr_status Debug cable internal status - Offset: `0x78` - Reset default: `0x0` -- Reset mask: `0x1ff` +- Reset mask: `0x3ff` ### Fields ```wavejson -{"reg": [{"name": "filter_match", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"name": "oneshot", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 90}} +{"reg": [{"name": "MATCH", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"name": "TRANS", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "ONESHOT", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 22}], "config": {"lanes": 1, "fontsize": 10, "vspace": 90}} ``` -| Bits | Type | Reset | Name | Description | -|:------:|:------:|:-------:|:-------------|:-----------------------------------------------------------| -| 31:9 | | | | Reserved | -| 8 | rw1c | 0x0 | oneshot | 0: oneshot sample is not done ; 1: oneshot sample is done | -| 7:0 | rw1c | 0x0 | filter_match | 0: filter condition is not met; 1: filter condition is met | +| Bits | Type | Reset | Name | Description | +|:------:|:------:|:-------:|:--------|:-----------------------------------------------------------| +| 31:10 | | | | Reserved | +| 9 | rw1c | 0x0 | ONESHOT | 0: oneshot sample is not done ; 1: oneshot sample is done | +| 8 | rw1c | 0x0 | TRANS | 0: transition did not occur; 1: transition occurred | +| 7:0 | rw1c | 0x0 | MATCH | 0: filter condition is not met; 1: filter condition is met | ## adc_fsm_state State of the internal state machine diff --git a/hw/ip/adc_ctrl/rtl/adc_ctrl.sv b/hw/ip/adc_ctrl/rtl/adc_ctrl.sv index 23a8376b088376..2d2c987894d4e3 100644 --- a/hw/ip/adc_ctrl/rtl/adc_ctrl.sv +++ b/hw/ip/adc_ctrl/rtl/adc_ctrl.sv @@ -93,9 +93,12 @@ module adc_ctrl .intr_o(intr_match_done_o), .adc_i(adc_i), .adc_o(adc_o), - .fsm_state_o(hw2reg.adc_fsm_state.d) + .aon_fsm_state_o(hw2reg.adc_fsm_state.d) ); + + + // All outputs should be known value after reset `ASSERT_KNOWN(IntrKnown, intr_match_done_o) `ASSERT_KNOWN(WakeKnown, wkup_req_o) diff --git a/hw/ip/adc_ctrl/rtl/adc_ctrl_core.sv b/hw/ip/adc_ctrl/rtl/adc_ctrl_core.sv index d9819c0324d308..f08f00e7e44376 100644 --- a/hw/ip/adc_ctrl/rtl/adc_ctrl_core.sv +++ b/hw/ip/adc_ctrl/rtl/adc_ctrl_core.sv @@ -28,7 +28,7 @@ module adc_ctrl_core import adc_ctrl_reg_pkg::* ; ( output ast_pkg::adc_ast_req_t adc_o, // FSM state output for debug purposes. - output fsm_state_e fsm_state_o + output adc_ctrl_pkg::fsm_state_e aon_fsm_state_o ); logic chn0_val_we, chn1_val_we;//write enable for the latest ADC sample @@ -36,6 +36,7 @@ module adc_ctrl_core import adc_ctrl_reg_pkg::* ; ( logic [NumAdcFilter-1:0] chn0_match, chn1_match, match; logic [NumAdcFilter-1:0] match_pulse; + logic aon_fsm_trans; //write enable for the ADC sample when the interrupt is triggered logic adc_ctrl_done, oneshot_done; @@ -133,13 +134,18 @@ module adc_ctrl_core import adc_ctrl_reg_pkg::* ; ( end // adc filter status - assign aon_filter_status_o.d = match_pulse | reg2hw_i.filter_status.q; - assign aon_filter_status_o.de = |match_pulse; + assign aon_filter_status_o.filter_match.d = match_pulse | reg2hw_i.filter_status.filter_match.q; + assign aon_filter_status_o.filter_match.de = |match_pulse; + // transition status + assign aon_filter_status_o.trans.d = aon_fsm_trans | reg2hw_i.filter_status.trans.q; + assign aon_filter_status_o.trans.de = aon_fsm_trans; // generate wakeup to external power manager if filter status // and wakeup enable are set. - assign wkup_req_o = |(reg2hw_i.filter_status.q & - reg2hw_i.adc_wakeup_ctl.q); + assign wkup_req_o = |(reg2hw_i.filter_status.filter_match.q & + reg2hw_i.adc_wakeup_ctl.filter_match.q) || + (reg2hw_i.filter_status.trans.q & + reg2hw_i.adc_wakeup_ctl.trans.q); //instantiate the main state machine adc_ctrl_fsm u_adc_ctrl_fsm ( @@ -166,7 +172,8 @@ module adc_ctrl_core import adc_ctrl_reg_pkg::* ; ( .chn1_val_o(chn1_val), .adc_ctrl_done_o(adc_ctrl_done), .oneshot_done_o(oneshot_done), - .fsm_state_o + .aon_fsm_state_o, + .aon_fsm_trans_o(aon_fsm_trans) ); // synchronzie from clk_aon into cfg domain @@ -182,13 +189,18 @@ module adc_ctrl_core import adc_ctrl_reg_pkg::* ; ( //Instantiate the interrupt module adc_ctrl_intr u_adc_ctrl_intr ( + .clk_i, + .rst_ni, .clk_aon_i, .rst_aon_ni, .aon_filter_match_i(match_pulse), - .clk_i, - .rst_ni, - .cfg_intr_en_i(reg2hw_i.adc_intr_ctl.q), + .aon_fsm_trans_i(aon_fsm_trans), .cfg_oneshot_done_i(cfg_oneshot_done), + .cfg_intr_en_i(reg2hw_i.adc_intr_ctl.en.q), + .cfg_wkup_en_i(reg2hw_i.adc_wakeup_ctl.en.q), + .cfg_intr_trans_en_i(reg2hw_i.adc_intr_ctl.trans_en.q), + .cfg_wkup_trans_en_i(reg2hw_i.adc_wakeup_ctl.trans_en.q), + .cfg_oneshot_done_en_i(reg2hw_i.adc_intr_ctl.oneshot_en.q), .intr_state_i(reg2hw_i.intr_state), .intr_enable_i(reg2hw_i.intr_enable), .intr_test_i(reg2hw_i.intr_test), diff --git a/hw/ip/adc_ctrl/rtl/adc_ctrl_fsm.sv b/hw/ip/adc_ctrl/rtl/adc_ctrl_fsm.sv index 5fe37732750b06..4d44ccf3ec787e 100644 --- a/hw/ip/adc_ctrl/rtl/adc_ctrl_fsm.sv +++ b/hw/ip/adc_ctrl/rtl/adc_ctrl_fsm.sv @@ -29,7 +29,8 @@ module adc_ctrl_fsm output logic [9:0] chn1_val_o, output logic adc_ctrl_done_o, output logic oneshot_done_o, - output fsm_state_e fsm_state_o // FSM state output for debug purposes + output fsm_state_e aon_fsm_state_o, // FSM state output for debug purposes + output logic aon_fsm_trans_o // FSM lp -> np transition indication pulse ); logic trigger_q; @@ -54,7 +55,7 @@ module adc_ctrl_fsm fsm_state_e fsm_state_q, fsm_state_d; - assign fsm_state_o = fsm_state_q; + assign aon_fsm_state_o = fsm_state_q; always_ff @(posedge clk_aon_i or negedge rst_aon_ni) begin if (!rst_aon_ni) begin @@ -185,7 +186,6 @@ module adc_ctrl_fsm assign lp_sample_cnt_thresh = cfg_lp_sample_cnt_i - 1'b1; assign np_sample_cnt_thresh = cfg_np_sample_cnt_i - 1'b1; - always_comb begin: adc_fsm fsm_state_d = fsm_state_q; //outputs @@ -202,6 +202,7 @@ module adc_ctrl_fsm adc_ctrl_done_o = 1'b0; oneshot_done_o = 1'b0; ld_match = 1'b0; + aon_fsm_trans_o = 1'b0; unique case (fsm_state_q) PWRDN: begin @@ -289,6 +290,7 @@ module adc_ctrl_fsm end else if (lp_sample_cnt_q == lp_sample_cnt_thresh) begin fsm_state_d = NP_0; lp_sample_cnt_clr = 1'b1; + aon_fsm_trans_o = 1'b1; end end end diff --git a/hw/ip/adc_ctrl/rtl/adc_ctrl_intr.sv b/hw/ip/adc_ctrl/rtl/adc_ctrl_intr.sv index ee61aacb087433..d3120bf7467bbf 100644 --- a/hw/ip/adc_ctrl/rtl/adc_ctrl_intr.sv +++ b/hw/ip/adc_ctrl/rtl/adc_ctrl_intr.sv @@ -4,16 +4,25 @@ // // Description: adc_ctrl interrupt Module // -module adc_ctrl_intr import adc_ctrl_reg_pkg::*; ( +module adc_ctrl_intr + import adc_ctrl_reg_pkg::*; +#( +) ( input clk_aon_i, input rst_aon_ni, input clk_i, input rst_ni, input [NumAdcFilter-1:0] aon_filter_match_i, - input [8:0] cfg_intr_en_i, + input aon_fsm_trans_i, input cfg_oneshot_done_i, + input [NumAdcFilter-1:0] cfg_intr_en_i, + input [NumAdcFilter-1:0] cfg_wkup_en_i, + input cfg_intr_trans_en_i, + input cfg_wkup_trans_en_i, + input cfg_oneshot_done_en_i, + input adc_ctrl_reg2hw_intr_state_reg_t intr_state_i, input adc_ctrl_reg2hw_intr_enable_reg_t intr_enable_i, input adc_ctrl_reg2hw_intr_test_reg_t intr_test_i, @@ -26,46 +35,50 @@ module adc_ctrl_intr import adc_ctrl_reg_pkg::*; ( ); - // aon_filter_match is split into staging and request portions. + // Number of filters and FSM transition interrupt. + localparam int NumAonIntrEvents = NumAdcFilter + 1; + logic [NumAonIntrEvents-1:0] aon_reqs; + assign aon_reqs = {aon_fsm_trans_i, aon_filter_match_i}; + + // aon interrupt requests are split into staging and request portions. // The staging portion always absorbs the incoming event pulse. // The request portion on the other hand does not change until // a request/ack handshake cycle has completed. - - logic [NumAdcFilter-1:0] staging_filter_match; + logic [NumAonIntrEvents-1:0] staging_reqs_q; logic aon_ld_req; // staging portion takes on the value of the incoming event match // and clears when it is snapshot into request hold. always_ff @(posedge clk_aon_i or negedge rst_aon_ni) begin if (!rst_aon_ni) begin - staging_filter_match <= '0; - end else if (aon_ld_req && |aon_filter_match_i) begin - staging_filter_match <= aon_filter_match_i; + staging_reqs_q <= '0; + end else if (aon_ld_req && |aon_reqs) begin + staging_reqs_q <= aon_reqs; end else if (aon_ld_req) begin - staging_filter_match <= '0; - end else if (|aon_filter_match_i) begin - staging_filter_match <= staging_filter_match | aon_filter_match_i; + staging_reqs_q <= '0; + end else if (|aon_reqs) begin + staging_reqs_q <= staging_reqs_q | aon_reqs; end end - logic [NumAdcFilter-1:0] aon_req_hold; + logic [NumAonIntrEvents-1:0] aon_req_hold_q; logic aon_ack; // staging has pending requsts - assign aon_ld_req = (aon_req_hold == '0) & |staging_filter_match; + assign aon_ld_req = (aon_req_hold_q == '0) & |staging_reqs_q; // request hold self clears when the handshake cycle is complete always_ff @(posedge clk_aon_i or negedge rst_aon_ni) begin - if (!rst_aon_ni) begin - aon_req_hold <= '0; - end else if (aon_ld_req) begin - aon_req_hold <= staging_filter_match; - end else if (aon_ack) begin - aon_req_hold <= '0; - end + if (!rst_aon_ni) begin + aon_req_hold_q <= '0; + end else if (aon_ld_req) begin + aon_req_hold_q <= staging_reqs_q; + end else if (aon_ack) begin + aon_req_hold_q <= '0; + end end - logic filter_match_event; + logic dst_ack; prim_sync_reqack u_match_sync ( .clk_src_i(clk_aon_i), .rst_src_ni(rst_aon_ni), @@ -74,29 +87,33 @@ module adc_ctrl_intr import adc_ctrl_reg_pkg::*; ( .req_chk_i(1'b1), .src_req_i(|aon_req_hold), .src_ack_o(aon_ack), - .dst_req_o(filter_match_event), - .dst_ack_i(filter_match_event) + .dst_req_o(dst_ack), + .dst_ack_i(dst_ack) ); - //To write into interrupt status register - logic [1+NumAdcFilter-1:0] intr_events; + // To write into interrupt status register. Note that we're also adding the non-AON interrupt + // source cfg_oneshot_done_i at this point. + logic [1+NumAonIntrEvents-1:0] intr_events; // Note that aon_req_hold is a value held in an async domain. // aon_req_hold's value should not change until handshake is completed by `prim_sync_reqack`. // There is no reason to use `prim_sync_reqack` in this case because that module passes // through data only when the direction is src->dst. - assign intr_events = {cfg_oneshot_done_i, - {NumAdcFilter{filter_match_event}} & aon_req_hold} & cfg_intr_en_i; + assign intr_events = {cfg_oneshot_done_i, {NumAonIntrEvents{dst_ack}} & aon_req_hold_q} & + {cfg_oneshot_done_en_i, cfg_intr_trans_en_i, cfg_intr_en_i}; - assign adc_intr_status_o.filter_match.de = |intr_events[7:0]; - assign adc_intr_status_o.oneshot.de = intr_events[8]; + assign adc_intr_status_o.match.de = |intr_events[7:0]; + assign adc_intr_status_o.trans.de = intr_events[8]; + assign adc_intr_status_o.oneshot.de = intr_events[9]; // since interrupt events are pulsed, when successive events arrive we need to make sure to // hold the previously latched values - assign adc_intr_status_o.filter_match.d = intr_events[7:0] | adc_intr_status_i.filter_match.q; + assign adc_intr_status_o.match.d = intr_events[7:0] | adc_intr_status_i.match.q; - logic unused_oneshot; - assign unused_oneshot = adc_intr_status_i.oneshot.q; + logic unused_sigs; + assign unused_sigs = ^{adc_intr_status_i.oneshot.q, + adc_intr_status_i.trans.q}; + assign adc_intr_status_o.trans.d = 1'b1; assign adc_intr_status_o.oneshot.d = 1'b1; // instantiate interrupt hardware primitive diff --git a/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_pkg.sv b/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_pkg.sv index 099a8499c910b4..24528bdbeec856 100644 --- a/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_pkg.sv +++ b/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_pkg.sv @@ -100,24 +100,45 @@ package adc_ctrl_reg_pkg; } adc_ctrl_reg2hw_adc_chn1_filter_ctl_mreg_t; typedef struct packed { - logic [7:0] q; + struct packed { + logic q; + } trans_en; + struct packed { + logic [7:0] q; + } match_en; } adc_ctrl_reg2hw_adc_wakeup_ctl_reg_t; typedef struct packed { - logic [7:0] q; + struct packed { + logic q; + } trans; + struct packed { + logic [7:0] q; + } match; } adc_ctrl_reg2hw_filter_status_reg_t; typedef struct packed { - logic [8:0] q; + struct packed { + logic q; + } oneshot_en; + struct packed { + logic q; + } trans_en; + struct packed { + logic [7:0] q; + } match_en; } adc_ctrl_reg2hw_adc_intr_ctl_reg_t; typedef struct packed { struct packed { logic q; } oneshot; + struct packed { + logic q; + } trans; struct packed { logic [7:0] q; - } filter_match; + } match; } adc_ctrl_reg2hw_adc_intr_status_reg_t; typedef struct packed { @@ -145,15 +166,25 @@ package adc_ctrl_reg_pkg; } adc_ctrl_hw2reg_adc_chn_val_mreg_t; typedef struct packed { - logic [7:0] d; - logic de; + struct packed { + logic [7:0] d; + logic de; + } match; + struct packed { + logic d; + logic de; + } trans; } adc_ctrl_hw2reg_filter_status_reg_t; typedef struct packed { struct packed { logic [7:0] d; logic de; - } filter_match; + } match; + struct packed { + logic d; + logic de; + } trans; struct packed { logic d; logic de; @@ -166,29 +197,29 @@ package adc_ctrl_reg_pkg; // Register -> HW type typedef struct packed { - adc_ctrl_reg2hw_intr_state_reg_t intr_state; // [447:447] - adc_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [446:446] - adc_ctrl_reg2hw_intr_test_reg_t intr_test; // [445:444] - adc_ctrl_reg2hw_alert_test_reg_t alert_test; // [443:442] - adc_ctrl_reg2hw_adc_en_ctl_reg_t adc_en_ctl; // [441:440] - adc_ctrl_reg2hw_adc_pd_ctl_reg_t adc_pd_ctl; // [439:411] - adc_ctrl_reg2hw_adc_lp_sample_ctl_reg_t adc_lp_sample_ctl; // [410:403] - adc_ctrl_reg2hw_adc_sample_ctl_reg_t adc_sample_ctl; // [402:387] - adc_ctrl_reg2hw_adc_fsm_rst_reg_t adc_fsm_rst; // [386:386] - adc_ctrl_reg2hw_adc_chn0_filter_ctl_mreg_t [7:0] adc_chn0_filter_ctl; // [385:210] - adc_ctrl_reg2hw_adc_chn1_filter_ctl_mreg_t [7:0] adc_chn1_filter_ctl; // [209:34] - adc_ctrl_reg2hw_adc_wakeup_ctl_reg_t adc_wakeup_ctl; // [33:26] - adc_ctrl_reg2hw_filter_status_reg_t filter_status; // [25:18] - adc_ctrl_reg2hw_adc_intr_ctl_reg_t adc_intr_ctl; // [17:9] - adc_ctrl_reg2hw_adc_intr_status_reg_t adc_intr_status; // [8:0] + adc_ctrl_reg2hw_intr_state_reg_t intr_state; // [451:451] + adc_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [450:450] + adc_ctrl_reg2hw_intr_test_reg_t intr_test; // [449:448] + adc_ctrl_reg2hw_alert_test_reg_t alert_test; // [447:446] + adc_ctrl_reg2hw_adc_en_ctl_reg_t adc_en_ctl; // [445:444] + adc_ctrl_reg2hw_adc_pd_ctl_reg_t adc_pd_ctl; // [443:415] + adc_ctrl_reg2hw_adc_lp_sample_ctl_reg_t adc_lp_sample_ctl; // [414:407] + adc_ctrl_reg2hw_adc_sample_ctl_reg_t adc_sample_ctl; // [406:391] + adc_ctrl_reg2hw_adc_fsm_rst_reg_t adc_fsm_rst; // [390:390] + adc_ctrl_reg2hw_adc_chn0_filter_ctl_mreg_t [7:0] adc_chn0_filter_ctl; // [389:214] + adc_ctrl_reg2hw_adc_chn1_filter_ctl_mreg_t [7:0] adc_chn1_filter_ctl; // [213:38] + adc_ctrl_reg2hw_adc_wakeup_ctl_reg_t adc_wakeup_ctl; // [37:29] + adc_ctrl_reg2hw_filter_status_reg_t filter_status; // [28:20] + adc_ctrl_reg2hw_adc_intr_ctl_reg_t adc_intr_ctl; // [19:10] + adc_ctrl_reg2hw_adc_intr_status_reg_t adc_intr_status; // [9:0] } adc_ctrl_reg2hw_t; // HW -> register type typedef struct packed { - adc_ctrl_hw2reg_intr_state_reg_t intr_state; // [82:81] - adc_ctrl_hw2reg_adc_chn_val_mreg_t [1:0] adc_chn_val; // [80:25] - adc_ctrl_hw2reg_filter_status_reg_t filter_status; // [24:16] - adc_ctrl_hw2reg_adc_intr_status_reg_t adc_intr_status; // [15:5] + adc_ctrl_hw2reg_intr_state_reg_t intr_state; // [86:85] + adc_ctrl_hw2reg_adc_chn_val_mreg_t [1:0] adc_chn_val; // [84:29] + adc_ctrl_hw2reg_filter_status_reg_t filter_status; // [28:18] + adc_ctrl_hw2reg_adc_intr_status_reg_t adc_intr_status; // [17:5] adc_ctrl_hw2reg_adc_fsm_state_reg_t adc_fsm_state; // [4:0] } adc_ctrl_hw2reg_t; @@ -299,8 +330,8 @@ package adc_ctrl_reg_pkg; 4'b 1111, // index[24] ADC_CTRL_ADC_CHN1_FILTER_CTL_7 4'b 1111, // index[25] ADC_CTRL_ADC_CHN_VAL_0 4'b 1111, // index[26] ADC_CTRL_ADC_CHN_VAL_1 - 4'b 0001, // index[27] ADC_CTRL_ADC_WAKEUP_CTL - 4'b 0001, // index[28] ADC_CTRL_FILTER_STATUS + 4'b 0011, // index[27] ADC_CTRL_ADC_WAKEUP_CTL + 4'b 0011, // index[28] ADC_CTRL_FILTER_STATUS 4'b 0011, // index[29] ADC_CTRL_ADC_INTR_CTL 4'b 0011, // index[30] ADC_CTRL_ADC_INTR_STATUS 4'b 0001 // index[31] ADC_CTRL_ADC_FSM_STATE diff --git a/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_top.sv b/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_top.sv index f081d3b0344999..d112cd5c442d76 100644 --- a/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_top.sv +++ b/hw/ip/adc_ctrl/rtl/adc_ctrl_reg_top.sv @@ -201,17 +201,23 @@ module adc_ctrl_reg_top ( logic [27:0] adc_chn_val_1_qs; logic adc_chn_val_1_busy; logic adc_wakeup_ctl_we; - logic [7:0] adc_wakeup_ctl_qs; + logic [8:0] adc_wakeup_ctl_qs; logic adc_wakeup_ctl_busy; logic filter_status_we; - logic [7:0] filter_status_qs; + logic [8:0] filter_status_qs; logic filter_status_busy; logic adc_intr_ctl_we; - logic [8:0] adc_intr_ctl_qs; - logic [8:0] adc_intr_ctl_wd; + logic [7:0] adc_intr_ctl_match_en_qs; + logic [7:0] adc_intr_ctl_match_en_wd; + logic adc_intr_ctl_trans_en_qs; + logic adc_intr_ctl_trans_en_wd; + logic adc_intr_ctl_oneshot_en_qs; + logic adc_intr_ctl_oneshot_en_wd; logic adc_intr_status_we; - logic [7:0] adc_intr_status_filter_match_qs; - logic [7:0] adc_intr_status_filter_match_wd; + logic [7:0] adc_intr_status_match_qs; + logic [7:0] adc_intr_status_match_wd; + logic adc_intr_status_trans_qs; + logic adc_intr_status_trans_wd; logic adc_intr_status_oneshot_qs; logic adc_intr_status_oneshot_wd; logic adc_fsm_state_re; @@ -1220,21 +1226,23 @@ module adc_ctrl_reg_top ( .dst_wd_o () ); - logic [7:0] aon_adc_wakeup_ctl_qs_int; - logic [7:0] aon_adc_wakeup_ctl_qs; - logic [7:0] aon_adc_wakeup_ctl_wdata; + logic [7:0] aon_adc_wakeup_ctl_match_en_qs_int; + logic aon_adc_wakeup_ctl_trans_en_qs_int; + logic [8:0] aon_adc_wakeup_ctl_qs; + logic [8:0] aon_adc_wakeup_ctl_wdata; logic aon_adc_wakeup_ctl_we; logic unused_aon_adc_wakeup_ctl_wdata; always_comb begin - aon_adc_wakeup_ctl_qs = 8'h0; - aon_adc_wakeup_ctl_qs = aon_adc_wakeup_ctl_qs_int; + aon_adc_wakeup_ctl_qs = 9'h0; + aon_adc_wakeup_ctl_qs[7:0] = aon_adc_wakeup_ctl_match_en_qs_int; + aon_adc_wakeup_ctl_qs[8] = aon_adc_wakeup_ctl_trans_en_qs_int; end prim_reg_cdc #( - .DataWidth(8), - .ResetVal(8'h0), - .BitMask(8'hff), + .DataWidth(9), + .ResetVal(9'h0), + .BitMask(9'h1ff), .DstWrReq(0) ) u_adc_wakeup_ctl_cdc ( .clk_src_i (clk_i), @@ -1244,7 +1252,7 @@ module adc_ctrl_reg_top ( .src_regwen_i ('0), .src_we_i (adc_wakeup_ctl_we), .src_re_i ('0), - .src_wd_i (reg_wdata[7:0]), + .src_wd_i (reg_wdata[8:0]), .src_busy_o (adc_wakeup_ctl_busy), .src_qs_o (adc_wakeup_ctl_qs), // for software read back .dst_update_i ('0), @@ -1258,26 +1266,30 @@ module adc_ctrl_reg_top ( assign unused_aon_adc_wakeup_ctl_wdata = ^aon_adc_wakeup_ctl_wdata; - logic [7:0] aon_filter_status_ds_int; - logic [7:0] aon_filter_status_qs_int; - logic [7:0] aon_filter_status_ds; + logic [7:0] aon_filter_status_match_ds_int; + logic [7:0] aon_filter_status_match_qs_int; + logic aon_filter_status_trans_ds_int; + logic aon_filter_status_trans_qs_int; + logic [8:0] aon_filter_status_ds; logic aon_filter_status_qe; - logic [7:0] aon_filter_status_qs; - logic [7:0] aon_filter_status_wdata; + logic [8:0] aon_filter_status_qs; + logic [8:0] aon_filter_status_wdata; logic aon_filter_status_we; logic unused_aon_filter_status_wdata; always_comb begin - aon_filter_status_qs = 8'h0; - aon_filter_status_ds = 8'h0; - aon_filter_status_ds = aon_filter_status_ds_int; - aon_filter_status_qs = aon_filter_status_qs_int; + aon_filter_status_qs = 9'h0; + aon_filter_status_ds = 9'h0; + aon_filter_status_ds[7:0] = aon_filter_status_match_ds_int; + aon_filter_status_qs[7:0] = aon_filter_status_match_qs_int; + aon_filter_status_ds[8] = aon_filter_status_trans_ds_int; + aon_filter_status_qs[8] = aon_filter_status_trans_qs_int; end prim_reg_cdc #( - .DataWidth(8), - .ResetVal(8'h0), - .BitMask(8'hff), + .DataWidth(9), + .ResetVal(9'h0), + .BitMask(9'h1ff), .DstWrReq(1) ) u_filter_status_cdc ( .clk_src_i (clk_i), @@ -1287,7 +1299,7 @@ module adc_ctrl_reg_top ( .src_regwen_i ('0), .src_we_i (filter_status_we), .src_re_i ('0), - .src_wd_i (reg_wdata[7:0]), + .src_wd_i (reg_wdata[8:0]), .src_busy_o (filter_status_busy), .src_qs_o (filter_status_qs), // for software read back .dst_update_i (aon_filter_status_qe), @@ -3663,12 +3675,13 @@ module adc_ctrl_reg_top ( // R[adc_wakeup_ctl]: V(False) + // F[match_en]: 7:0 prim_subreg #( .DW (8), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (8'h0), .Mubi (1'b0) - ) u_adc_wakeup_ctl ( + ) u_adc_wakeup_ctl_match_en ( .clk_i (clk_aon_i), .rst_ni (rst_aon_ni), @@ -3682,23 +3695,51 @@ module adc_ctrl_reg_top ( // to internal hardware .qe (), - .q (reg2hw.adc_wakeup_ctl.q), + .q (reg2hw.adc_wakeup_ctl.match_en.q), + .ds (), + + // to register interface (read) + .qs (aon_adc_wakeup_ctl_match_en_qs_int) + ); + + // F[trans_en]: 8:8 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_adc_wakeup_ctl_trans_en ( + .clk_i (clk_aon_i), + .rst_ni (rst_aon_ni), + + // from register interface + .we (aon_adc_wakeup_ctl_we), + .wd (aon_adc_wakeup_ctl_wdata[8]), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.adc_wakeup_ctl.trans_en.q), .ds (), // to register interface (read) - .qs (aon_adc_wakeup_ctl_qs_int) + .qs (aon_adc_wakeup_ctl_trans_en_qs_int) ); // R[filter_status]: V(False) - logic [0:0] filter_status_flds_we; + logic [1:0] filter_status_flds_we; assign aon_filter_status_qe = |filter_status_flds_we; + // F[match]: 7:0 prim_subreg #( .DW (8), .SwAccess(prim_subreg_pkg::SwAccessW1C), .RESVAL (8'h0), .Mubi (1'b0) - ) u_filter_status ( + ) u_filter_status_match ( .clk_i (clk_aon_i), .rst_ni (rst_aon_ni), @@ -3707,32 +3748,60 @@ module adc_ctrl_reg_top ( .wd (aon_filter_status_wdata[7:0]), // from internal hardware - .de (hw2reg.filter_status.de), - .d (hw2reg.filter_status.d), + .de (hw2reg.filter_status.match.de), + .d (hw2reg.filter_status.match.d), // to internal hardware .qe (filter_status_flds_we[0]), - .q (reg2hw.filter_status.q), - .ds (aon_filter_status_ds_int), + .q (reg2hw.filter_status.match.q), + .ds (aon_filter_status_match_ds_int), // to register interface (read) - .qs (aon_filter_status_qs_int) + .qs (aon_filter_status_match_qs_int) + ); + + // F[trans]: 8:8 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW1C), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_filter_status_trans ( + .clk_i (clk_aon_i), + .rst_ni (rst_aon_ni), + + // from register interface + .we (aon_filter_status_we), + .wd (aon_filter_status_wdata[8]), + + // from internal hardware + .de (hw2reg.filter_status.trans.de), + .d (hw2reg.filter_status.trans.d), + + // to internal hardware + .qe (filter_status_flds_we[1]), + .q (reg2hw.filter_status.trans.q), + .ds (aon_filter_status_trans_ds_int), + + // to register interface (read) + .qs (aon_filter_status_trans_qs_int) ); // R[adc_intr_ctl]: V(False) + // F[match_en]: 7:0 prim_subreg #( - .DW (9), + .DW (8), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (9'h0), + .RESVAL (8'h0), .Mubi (1'b0) - ) u_adc_intr_ctl ( + ) u_adc_intr_ctl_match_en ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface .we (adc_intr_ctl_we), - .wd (adc_intr_ctl_wd), + .wd (adc_intr_ctl_match_en_wd), // from internal hardware .de (1'b0), @@ -3740,43 +3809,124 @@ module adc_ctrl_reg_top ( // to internal hardware .qe (), - .q (reg2hw.adc_intr_ctl.q), + .q (reg2hw.adc_intr_ctl.match_en.q), .ds (), // to register interface (read) - .qs (adc_intr_ctl_qs) + .qs (adc_intr_ctl_match_en_qs) + ); + + // F[trans_en]: 8:8 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_adc_intr_ctl_trans_en ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (adc_intr_ctl_we), + .wd (adc_intr_ctl_trans_en_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.adc_intr_ctl.trans_en.q), + .ds (), + + // to register interface (read) + .qs (adc_intr_ctl_trans_en_qs) + ); + + // F[oneshot_en]: 9:9 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_adc_intr_ctl_oneshot_en ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (adc_intr_ctl_we), + .wd (adc_intr_ctl_oneshot_en_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.adc_intr_ctl.oneshot_en.q), + .ds (), + + // to register interface (read) + .qs (adc_intr_ctl_oneshot_en_qs) ); // R[adc_intr_status]: V(False) - // F[filter_match]: 7:0 + // F[match]: 7:0 prim_subreg #( .DW (8), .SwAccess(prim_subreg_pkg::SwAccessW1C), .RESVAL (8'h0), .Mubi (1'b0) - ) u_adc_intr_status_filter_match ( + ) u_adc_intr_status_match ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface .we (adc_intr_status_we), - .wd (adc_intr_status_filter_match_wd), + .wd (adc_intr_status_match_wd), // from internal hardware - .de (hw2reg.adc_intr_status.filter_match.de), - .d (hw2reg.adc_intr_status.filter_match.d), + .de (hw2reg.adc_intr_status.match.de), + .d (hw2reg.adc_intr_status.match.d), // to internal hardware .qe (), - .q (reg2hw.adc_intr_status.filter_match.q), + .q (reg2hw.adc_intr_status.match.q), .ds (), // to register interface (read) - .qs (adc_intr_status_filter_match_qs) + .qs (adc_intr_status_match_qs) ); - // F[oneshot]: 8:8 + // F[trans]: 8:8 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW1C), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_adc_intr_status_trans ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (adc_intr_status_we), + .wd (adc_intr_status_trans_wd), + + // from internal hardware + .de (hw2reg.adc_intr_status.trans.de), + .d (hw2reg.adc_intr_status.trans.d), + + // to internal hardware + .qe (), + .q (reg2hw.adc_intr_status.trans.q), + .ds (), + + // to register interface (read) + .qs (adc_intr_status_trans_qs) + ); + + // F[oneshot]: 9:9 prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessW1C), @@ -4007,16 +4157,24 @@ module adc_ctrl_reg_top ( assign adc_wakeup_ctl_we = addr_hit[27] & reg_we & !reg_error; + assign filter_status_we = addr_hit[28] & reg_we & !reg_error; + assign adc_intr_ctl_we = addr_hit[29] & reg_we & !reg_error; - assign adc_intr_ctl_wd = reg_wdata[8:0]; + assign adc_intr_ctl_match_en_wd = reg_wdata[7:0]; + + assign adc_intr_ctl_trans_en_wd = reg_wdata[8]; + + assign adc_intr_ctl_oneshot_en_wd = reg_wdata[9]; assign adc_intr_status_we = addr_hit[30] & reg_we & !reg_error; - assign adc_intr_status_filter_match_wd = reg_wdata[7:0]; + assign adc_intr_status_match_wd = reg_wdata[7:0]; + + assign adc_intr_status_trans_wd = reg_wdata[8]; - assign adc_intr_status_oneshot_wd = reg_wdata[8]; + assign adc_intr_status_oneshot_wd = reg_wdata[9]; assign adc_fsm_state_re = addr_hit[31] & reg_re & !reg_error; // Assign write-enables to checker logic vector. @@ -4152,12 +4310,15 @@ module adc_ctrl_reg_top ( reg_rdata_next = DW'(filter_status_qs); end addr_hit[29]: begin - reg_rdata_next[8:0] = adc_intr_ctl_qs; + reg_rdata_next[7:0] = adc_intr_ctl_match_en_qs; + reg_rdata_next[8] = adc_intr_ctl_trans_en_qs; + reg_rdata_next[9] = adc_intr_ctl_oneshot_en_qs; end addr_hit[30]: begin - reg_rdata_next[7:0] = adc_intr_status_filter_match_qs; - reg_rdata_next[8] = adc_intr_status_oneshot_qs; + reg_rdata_next[7:0] = adc_intr_status_match_qs; + reg_rdata_next[8] = adc_intr_status_trans_qs; + reg_rdata_next[9] = adc_intr_status_oneshot_qs; end addr_hit[31]: begin diff --git a/sw/device/lib/dif/dif_adc_ctrl.c b/sw/device/lib/dif/dif_adc_ctrl.c index 0eed624ea66504..f188436f1be033 100644 --- a/sw/device/lib/dif/dif_adc_ctrl.c +++ b/sw/device/lib/dif/dif_adc_ctrl.c @@ -450,7 +450,7 @@ dif_result_t dif_adc_ctrl_irq_clear_causes(const dif_adc_ctrl_t *adc_ctrl, dif_result_t dif_adc_ctrl_filter_match_wakeup_set_enabled( const dif_adc_ctrl_t *adc_ctrl, dif_adc_ctrl_filter_t filter, dif_toggle_t enabled) { - if (adc_ctrl == NULL || filter >= ADC_CTRL_PARAM_NUM_ADC_FILTER || + if (adc_ctrl == NULL || filter >= (ADC_CTRL_PARAM_NUM_ADC_FILTER + 1) || !dif_is_valid_toggle(enabled)) { return kDifBadArg; } @@ -468,7 +468,7 @@ dif_result_t dif_adc_ctrl_filter_match_wakeup_set_enabled( dif_result_t dif_adc_ctrl_filter_match_wakeup_get_enabled( const dif_adc_ctrl_t *adc_ctrl, dif_adc_ctrl_filter_t filter, dif_toggle_t *is_enabled) { - if (adc_ctrl == NULL || filter >= ADC_CTRL_PARAM_NUM_ADC_FILTER || + if (adc_ctrl == NULL || filter >= (ADC_CTRL_PARAM_NUM_ADC_FILTER + 1) || is_enabled == NULL) { return kDifBadArg; } diff --git a/sw/device/lib/dif/dif_adc_ctrl.h b/sw/device/lib/dif/dif_adc_ctrl.h index 4303fc89ec4a26..73d29a19004584 100644 --- a/sw/device/lib/dif/dif_adc_ctrl.h +++ b/sw/device/lib/dif/dif_adc_ctrl.h @@ -73,7 +73,7 @@ typedef enum dif_adc_ctrl_channel { * instances that may be configured. */ typedef enum dif_adc_ctrl_filter { - DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_FILTER_ENUM_INIT_) + DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_FILTER_ENUM_INIT_) kDifAdcCtrlTrans, } dif_adc_ctrl_filter_t; #undef DIF_ADC_CTRL_FILTER_ENUM_INIT_ @@ -96,6 +96,10 @@ typedef enum dif_adc_ctrl_filter { */ typedef enum dif_adc_ctrl_irq_cause { DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_IRQ_CAUSE_ENUM_INIT_) + /** + * Sample ready cause in Oneshot mode. + */ + kDifAdcCtrlIrqCauseTrans = 1U << ADC_CTRL_ADC_INTR_STATUS_TRANS_BIT, /** * Sample ready cause in Oneshot mode. */ diff --git a/sw/device/lib/dif/dif_adc_ctrl_unittest.cc b/sw/device/lib/dif/dif_adc_ctrl_unittest.cc index 4bc9480cb35bb5..e59f52f20e37cd 100644 --- a/sw/device/lib/dif/dif_adc_ctrl_unittest.cc +++ b/sw/device/lib/dif/dif_adc_ctrl_unittest.cc @@ -417,9 +417,9 @@ TEST_F(FilterStatusTest, NullArgs) { TEST_F(FilterStatusTest, Success) { uint32_t status; - EXPECT_READ32(ADC_CTRL_FILTER_STATUS_REG_OFFSET, 0xFF); + EXPECT_READ32(ADC_CTRL_FILTER_STATUS_REG_OFFSET, 0x1FF); EXPECT_DIF_OK(dif_adc_ctrl_get_filter_status(&adc_ctrl_, &status)); - EXPECT_EQ(status, 0xFF); + EXPECT_EQ(status, 0x1FF); } class IrqGetCausesTest : public AdcCtrlTest {}; @@ -446,7 +446,7 @@ TEST_F(IrqClearCausesTest, NullHandle) { TEST_F(IrqClearCausesTest, BadCauses) { EXPECT_DIF_BADARG(dif_adc_ctrl_irq_clear_causes( - &adc_ctrl_, 1U << (ADC_CTRL_PARAM_NUM_ADC_FILTER + 1))); + &adc_ctrl_, 1U << (ADC_CTRL_PARAM_NUM_ADC_FILTER + 2))); } TEST_F(IrqClearCausesTest, Success) { @@ -455,8 +455,13 @@ TEST_F(IrqClearCausesTest, Success) { EXPECT_DIF_OK(dif_adc_ctrl_irq_clear_causes( &adc_ctrl_, kDifAdcCtrlIrqCauseFilter0 | kDifAdcCtrlIrqCauseFilter3)); - EXPECT_WRITE32(ADC_CTRL_FILTER_STATUS_REG_OFFSET, 0x1); - EXPECT_WRITE32(ADC_CTRL_ADC_INTR_STATUS_REG_OFFSET, 0x101); + EXPECT_WRITE32(ADC_CTRL_FILTER_STATUS_REG_OFFSET, 0x102); + EXPECT_WRITE32(ADC_CTRL_ADC_INTR_STATUS_REG_OFFSET, 0x102); + EXPECT_DIF_OK(dif_adc_ctrl_irq_clear_causes( + &adc_ctrl_, kDifAdcCtrlIrqCauseFilter1 | kDifAdcCtrlIrqCauseTrans)); + + EXPECT_WRITE32(ADC_CTRL_FILTER_STATUS_REG_OFFSET, 0x001); + EXPECT_WRITE32(ADC_CTRL_ADC_INTR_STATUS_REG_OFFSET, 0x201); EXPECT_DIF_OK(dif_adc_ctrl_irq_clear_causes( &adc_ctrl_, kDifAdcCtrlIrqCauseFilter0 | kDifAdcCtrlIrqCauseOneshot)); } @@ -471,7 +476,7 @@ TEST_F(FilterMatchWakeupSetEnabledTest, NullHandle) { TEST_F(FilterMatchWakeupSetEnabledTest, BadFilter) { EXPECT_DIF_BADARG(dif_adc_ctrl_filter_match_wakeup_set_enabled( &adc_ctrl_, - static_cast(ADC_CTRL_PARAM_NUM_ADC_FILTER), + static_cast(ADC_CTRL_PARAM_NUM_ADC_FILTER + 1), kDifToggleEnabled)); } @@ -490,6 +495,11 @@ TEST_F(FilterMatchWakeupSetEnabledTest, Success) { EXPECT_WRITE32(ADC_CTRL_ADC_WAKEUP_CTL_REG_OFFSET, 0xF); EXPECT_DIF_OK(dif_adc_ctrl_filter_match_wakeup_set_enabled( &adc_ctrl_, kDifAdcCtrlFilter7, kDifToggleDisabled)); + + EXPECT_READ32(ADC_CTRL_ADC_WAKEUP_CTL_REG_OFFSET, 0xF); + EXPECT_WRITE32(ADC_CTRL_ADC_WAKEUP_CTL_REG_OFFSET, 0x10F); + EXPECT_DIF_OK(dif_adc_ctrl_filter_match_wakeup_set_enabled( + &adc_ctrl_, kDifAdcCtrlTrans, kDifToggleEnabled)); } class FilterMatchWakeupGetEnabledTest : public AdcCtrlTest {}; @@ -506,7 +516,7 @@ TEST_F(FilterMatchWakeupGetEnabledTest, BadFilter) { dif_toggle_t is_enabled; EXPECT_DIF_BADARG(dif_adc_ctrl_filter_match_wakeup_get_enabled( &adc_ctrl_, - static_cast(ADC_CTRL_PARAM_NUM_ADC_FILTER), + static_cast(ADC_CTRL_PARAM_NUM_ADC_FILTER + 1), &is_enabled)); }