[otp_ctrl] Connect test-related GPIO signal

Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/hw/ip/otp_ctrl/data/otp_ctrl.hjson b/hw/ip/otp_ctrl/data/otp_ctrl.hjson
index c88e11f..a313f15 100644
--- a/hw/ip/otp_ctrl/data/otp_ctrl.hjson
+++ b/hw/ip/otp_ctrl/data/otp_ctrl.hjson
@@ -21,6 +21,13 @@
     { protocol: "tlul", direction: "device", name: "prim" }
   ],
 
+  available_output_list: [
+    { name: "test",
+      width: 8,
+      desc: "Test-related GPIOs. Only active in DFT-enabled life cycle states."
+    }
+  ],
+
   ///////////////////////////
   // Interrupts and Alerts //
   ///////////////////////////
diff --git a/hw/ip/otp_ctrl/data/otp_ctrl.hjson.tpl b/hw/ip/otp_ctrl/data/otp_ctrl.hjson.tpl
index b973f74..55e4e91 100644
--- a/hw/ip/otp_ctrl/data/otp_ctrl.hjson.tpl
+++ b/hw/ip/otp_ctrl/data/otp_ctrl.hjson.tpl
@@ -34,6 +34,13 @@
     { protocol: "tlul", direction: "device", name: "prim" }
   ],
 
+  available_output_list: [
+    { name: "test",
+      width: 8,
+      desc: "Test-related GPIOs. Only active in DFT-enabled life cycle states."
+    }
+  ],
+
   ///////////////////////////
   // Interrupts and Alerts //
   ///////////////////////////
diff --git a/hw/ip/otp_ctrl/dv/tb.sv b/hw/ip/otp_ctrl/dv/tb.sv
index 7cb74a5..8d3a1f5 100644
--- a/hw/ip/otp_ctrl/dv/tb.sv
+++ b/hw/ip/otp_ctrl/dv/tb.sv
@@ -133,7 +133,11 @@
     //scan
     .scan_en_i                  (otp_ctrl_if.scan_en_i),
     .scan_rst_ni                (otp_ctrl_if.scan_rst_ni),
-    .scanmode_i                 (lc_ctrl_pkg::Off)
+    .scanmode_i                 (lc_ctrl_pkg::Off),
+
+    // Test-related GPIO output
+    .cio_test_o                 (),
+    .cio_test_en_o              ()
   );
 
   for (genvar i = 0; i < NumSramKeyReqSlots; i++) begin : gen_sram_pull_if
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl.sv
index f5537ef..1d4eb25 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl.sv
@@ -74,7 +74,10 @@
   // Scan
   input                                              scan_en_i,
   input                                              scan_rst_ni,
-  input lc_ctrl_pkg::lc_tx_t                         scanmode_i
+  input lc_ctrl_pkg::lc_tx_t                         scanmode_i,
+  // Test-related GPIO output
+  output logic [OtpTestCtrlWidth-1:0]                cio_test_o,
+  output logic [OtpTestCtrlWidth-1:0]                cio_test_en_o
 );
 
   import prim_util_pkg::vbits;
@@ -127,7 +130,7 @@
   ///////////////////////////////////////
 
   lc_ctrl_pkg::lc_tx_t       lc_creator_seed_sw_rw_en, lc_seed_hw_rd_en, lc_check_byp_en;
-  lc_ctrl_pkg::lc_tx_t [1:0] lc_dft_en;
+  lc_ctrl_pkg::lc_tx_t [2:0] lc_dft_en;
   // NumAgents + lfsr timer and scrambling datapath.
   lc_ctrl_pkg::lc_tx_t [NumAgentsIdx+1:0] lc_escalate_en, lc_escalate_en_synced;
   // Single wire for gating assertions in arbitration and CDC primitives.
@@ -161,7 +164,7 @@
   );
 
   prim_lc_sync #(
-    .NumCopies(2)
+    .NumCopies(3)
   ) u_prim_lc_sync_dft_en (
     .clk_i,
     .rst_ni,
@@ -654,6 +657,11 @@
   assign prim_tl_o         = (lc_dft_en[1] == lc_ctrl_pkg::On) ?
                              prim_tl_d2h_gated : '0;
 
+  // Test-related GPIOs.
+  logic [OtpTestCtrlWidth-1:0] otp_test_vect;
+  assign cio_test_o = (lc_dft_en[2] == lc_ctrl_pkg::On) ? otp_test_vect : '0;
+  assign cio_test_en_o = (lc_dft_en[2] == lc_ctrl_pkg::On) ? {OtpTestCtrlWidth{1'b1}} : '0;
+
   prim_otp #(
     .Width         ( OtpWidth            ),
     .Depth         ( OtpDepth            ),
@@ -671,6 +679,7 @@
     .ext_voltage_io   ( otp_ext_voltage_h_io           ),
     // Test interface
     .test_ctrl_i      ( lc_otp_program_i.otp_test_ctrl ),
+    .test_vect_o      ( otp_test_vect                  ),
     .test_tl_i        ( prim_tl_h2d_gated              ),
     .test_tl_o        ( prim_tl_d2h_gated              ),
     // Other DFT signals
diff --git a/hw/ip/prim_generic/rtl/prim_generic_otp.sv b/hw/ip/prim_generic/rtl/prim_generic_otp.sv
index 5e4a8ca..d190e62 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_otp.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_otp.sv
@@ -31,9 +31,10 @@
   // External programming voltage
   inout wire                     ext_voltage_io,
   // Test interface
-  input [TestCtrlWidth-1:0]      test_ctrl_i,
-  input  tlul_pkg::tl_h2d_t      test_tl_i,
-  output tlul_pkg::tl_d2h_t      test_tl_o,
+  input        [TestCtrlWidth-1:0] test_ctrl_i,
+  output logic [TestCtrlWidth-1:0] test_vect_o,
+  input  tlul_pkg::tl_h2d_t        test_tl_i,
+  output tlul_pkg::tl_d2h_t        test_tl_o,
   // Other DFT signals
   input lc_ctrl_pkg::lc_tx_t     scanmode_i,  // Scan Mode input
   input                          scan_en_i,   // Scan Shift
@@ -73,6 +74,8 @@
 
   assign otp_alert_src_o = '{p: '0, n: '1};
 
+  assign test_vect_o = '0;
+
   ////////////////////////////////////
   // TL-UL Test Interface Emulation //
   ////////////////////////////////////
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index a89a8dc..15945ad 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -9815,6 +9815,14 @@
         attr: ""
       }
       {
+        instance: otp_ctrl
+        port: test[0]
+        connection: muxed
+        pad: ""
+        desc: ""
+        attr: ""
+      }
+      {
         instance: sysrst_ctrl_aon
         port: ac_present
         connection: muxed
@@ -10972,6 +10980,16 @@
         glob_idx: 67
       }
       {
+        name: otp_ctrl_test
+        width: 8
+        type: output
+        idx: 0
+        pad: ""
+        attr: ""
+        connection: muxed
+        glob_idx: 68
+      }
+      {
         name: sysrst_ctrl_aon_bat_disable
         width: 1
         type: output
@@ -10979,7 +10997,7 @@
         pad: ""
         attr: ""
         connection: muxed
-        glob_idx: 68
+        glob_idx: 69
       }
       {
         name: sysrst_ctrl_aon_ec_rst_out_l
@@ -10999,7 +11017,7 @@
         pad: ""
         attr: ""
         connection: muxed
-        glob_idx: 69
+        glob_idx: 70
       }
       {
         name: sysrst_ctrl_aon_key1_out
@@ -11009,7 +11027,7 @@
         pad: ""
         attr: ""
         connection: muxed
-        glob_idx: 70
+        glob_idx: 71
       }
       {
         name: sysrst_ctrl_aon_key2_out
@@ -11019,7 +11037,7 @@
         pad: ""
         attr: ""
         connection: muxed
-        glob_idx: 71
+        glob_idx: 72
       }
       {
         name: sysrst_ctrl_aon_pwrb_out
@@ -11039,7 +11057,7 @@
         pad: ""
         attr: ""
         connection: muxed
-        glob_idx: 72
+        glob_idx: 73
       }
     ]
     io_counts:
@@ -11055,7 +11073,7 @@
       {
         inouts: 42
         inputs: 14
-        outputs: 31
+        outputs: 32
         pads: 47
       }
     }
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index e28fa7b..9b3be7d 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -1242,6 +1242,7 @@
       { instance: "flash_ctrl",      port: '',             connection: 'muxed' , pad: ''             , desc: ''},
       { instance: "sensor_ctrl_aon", port: '',             connection: 'muxed' , pad: ''             , desc: ''},
       { instance: "pwm_aon",         port: '',             connection: 'muxed' , pad: ''             , desc: ''},
+      { instance: "otp_ctrl",        port: 'test[0]',      connection: 'muxed' , pad: ''             , desc: ''},
       // Sysrst ctrl has both muxed and dedicated IOs
       { instance: "sysrst_ctrl_aon", port: 'ac_present',   connection: 'muxed' , pad: ''             , desc: ''},
       { instance: "sysrst_ctrl_aon", port: 'ec_rst_in_l',  connection: 'muxed' , pad: ''             , desc: ''},
diff --git a/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson b/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson
index 3376298..872095f 100644
--- a/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson
+++ b/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson
@@ -171,7 +171,7 @@
     { name: "NMioPeriphOut",
       desc: "Number of muxed peripheral outputs",
       type: "int",
-      default: "73",
+      default: "74",
       local: "true"
     },
     { name: "NMioPads",
diff --git a/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv b/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv
index 90e8fd3..5ab71c9 100644
--- a/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv
+++ b/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv
@@ -9,7 +9,7 @@
   // Param list
   parameter int AttrDw = 13;
   parameter int NMioPeriphIn = 56;
-  parameter int NMioPeriphOut = 73;
+  parameter int NMioPeriphOut = 74;
   parameter int NMioPads = 47;
   parameter int NDioPads = 24;
   parameter int NWkupDetect = 8;
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 1771266..a36d07a 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -187,8 +187,8 @@
 
   // Signals
   logic [55:0] mio_p2d;
-  logic [72:0] mio_d2p;
-  logic [72:0] mio_en_d2p;
+  logic [73:0] mio_d2p;
+  logic [73:0] mio_en_d2p;
   logic [23:0] dio_p2d;
   logic [23:0] dio_d2p;
   logic [23:0] dio_en_d2p;
@@ -289,6 +289,8 @@
   logic        cio_usbdev_dn_d2p;
   logic        cio_usbdev_dn_en_d2p;
   // otp_ctrl
+  logic [7:0]  cio_otp_ctrl_test_d2p;
+  logic [7:0]  cio_otp_ctrl_test_en_d2p;
   // lc_ctrl
   // alert_handler
   // pwrmgr_aon
@@ -1575,6 +1577,10 @@
     .RndCnstLfsrPerm(RndCnstOtpCtrlLfsrPerm)
   ) u_otp_ctrl (
 
+      // Output
+      .cio_test_o    (cio_otp_ctrl_test_d2p),
+      .cio_test_en_o (cio_otp_ctrl_test_en_d2p),
+
       // Interrupt
       .intr_otp_operation_done_o (intr_otp_ctrl_otp_operation_done),
       .intr_otp_error_o          (intr_otp_ctrl_otp_error),
@@ -3115,6 +3121,7 @@
   assign mio_d2p[MioOutPwmAonPwm3] = cio_pwm_aon_pwm_d2p[3];
   assign mio_d2p[MioOutPwmAonPwm4] = cio_pwm_aon_pwm_d2p[4];
   assign mio_d2p[MioOutPwmAonPwm5] = cio_pwm_aon_pwm_d2p[5];
+  assign mio_d2p[MioOutOtpCtrlTest0] = cio_otp_ctrl_test_d2p[0];
   assign mio_d2p[MioOutSysrstCtrlAonBatDisable] = cio_sysrst_ctrl_aon_bat_disable_d2p;
   assign mio_d2p[MioOutSysrstCtrlAonKey0Out] = cio_sysrst_ctrl_aon_key0_out_d2p;
   assign mio_d2p[MioOutSysrstCtrlAonKey1Out] = cio_sysrst_ctrl_aon_key1_out_d2p;
@@ -3190,6 +3197,7 @@
   assign mio_en_d2p[MioOutPwmAonPwm3] = cio_pwm_aon_pwm_en_d2p[3];
   assign mio_en_d2p[MioOutPwmAonPwm4] = cio_pwm_aon_pwm_en_d2p[4];
   assign mio_en_d2p[MioOutPwmAonPwm5] = cio_pwm_aon_pwm_en_d2p[5];
+  assign mio_en_d2p[MioOutOtpCtrlTest0] = cio_otp_ctrl_test_en_d2p[0];
   assign mio_en_d2p[MioOutSysrstCtrlAonBatDisable] = cio_sysrst_ctrl_aon_bat_disable_en_d2p;
   assign mio_en_d2p[MioOutSysrstCtrlAonKey0Out] = cio_sysrst_ctrl_aon_key0_out_en_d2p;
   assign mio_en_d2p[MioOutSysrstCtrlAonKey1Out] = cio_sysrst_ctrl_aon_key1_out_en_d2p;
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv
index 64f1045..9e91046 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv
@@ -661,12 +661,13 @@
     MioOutPwmAonPwm3 = 65,
     MioOutPwmAonPwm4 = 66,
     MioOutPwmAonPwm5 = 67,
-    MioOutSysrstCtrlAonBatDisable = 68,
-    MioOutSysrstCtrlAonKey0Out = 69,
-    MioOutSysrstCtrlAonKey1Out = 70,
-    MioOutSysrstCtrlAonKey2Out = 71,
-    MioOutSysrstCtrlAonZ3Wakeup = 72,
-    MioOutCount = 73
+    MioOutOtpCtrlTest0 = 68,
+    MioOutSysrstCtrlAonBatDisable = 69,
+    MioOutSysrstCtrlAonKey0Out = 70,
+    MioOutSysrstCtrlAonKey1Out = 71,
+    MioOutSysrstCtrlAonKey2Out = 72,
+    MioOutSysrstCtrlAonZ3Wakeup = 73,
+    MioOutCount = 74
   } mio_out_e;
 
   // Enumeration for DIO signals, used on both the top and chip-levels.
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.h b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
index 1dbe6ea..8a4ff88 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.h
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
@@ -1559,12 +1559,13 @@
   kTopEarlgreyPinmuxOutselPwmAonPwm3 = 68, /**< Peripheral Output 65 */
   kTopEarlgreyPinmuxOutselPwmAonPwm4 = 69, /**< Peripheral Output 66 */
   kTopEarlgreyPinmuxOutselPwmAonPwm5 = 70, /**< Peripheral Output 67 */
-  kTopEarlgreyPinmuxOutselSysrstCtrlAonBatDisable = 71, /**< Peripheral Output 68 */
-  kTopEarlgreyPinmuxOutselSysrstCtrlAonKey0Out = 72, /**< Peripheral Output 69 */
-  kTopEarlgreyPinmuxOutselSysrstCtrlAonKey1Out = 73, /**< Peripheral Output 70 */
-  kTopEarlgreyPinmuxOutselSysrstCtrlAonKey2Out = 74, /**< Peripheral Output 71 */
-  kTopEarlgreyPinmuxOutselSysrstCtrlAonZ3Wakeup = 75, /**< Peripheral Output 72 */
-  kTopEarlgreyPinmuxOutselLast = 75, /**< \internal Last valid outsel value */
+  kTopEarlgreyPinmuxOutselOtpCtrlTest0 = 71, /**< Peripheral Output 68 */
+  kTopEarlgreyPinmuxOutselSysrstCtrlAonBatDisable = 72, /**< Peripheral Output 69 */
+  kTopEarlgreyPinmuxOutselSysrstCtrlAonKey0Out = 73, /**< Peripheral Output 70 */
+  kTopEarlgreyPinmuxOutselSysrstCtrlAonKey1Out = 74, /**< Peripheral Output 71 */
+  kTopEarlgreyPinmuxOutselSysrstCtrlAonKey2Out = 75, /**< Peripheral Output 72 */
+  kTopEarlgreyPinmuxOutselSysrstCtrlAonZ3Wakeup = 76, /**< Peripheral Output 73 */
+  kTopEarlgreyPinmuxOutselLast = 76, /**< \internal Last valid outsel value */
 } top_earlgrey_pinmux_outsel_t;
 
 /**