[flash] Split scramble and ecc controls

- it is now possible to enable one without the other

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
index d4ace02..7b97df1 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
@@ -388,7 +388,14 @@
             { bits: "4",
               name: "SCRAMBLE_EN",
               desc: '''
-                Region is scramble and ECC enabled.
+                Region is scramble enabled.
+              ''',
+              resval: "0"
+            }
+            { bits: "5",
+              name: "ECC_EN",
+              desc: '''
+                Region is ECC enabled.
               ''',
               resval: "0"
             }
@@ -441,7 +448,14 @@
         { bits: "3",
           name: "SCRAMBLE_EN",
           desc: '''
-            Region is scramble and ECC enabled
+            Region is scrambleenabled
+          ''',
+          resval: "0"
+        }
+        { bits: "4",
+          name: "ECC_EN",
+          desc: '''
+            Region is ECC enabled
           ''',
           resval: "0"
         }
@@ -527,7 +541,14 @@
             { bits: "4",
               name: "SCRAMBLE_EN",
               desc: '''
-                Region is scramble and ECC enabled.
+                Region is scramble enabled.
+              ''',
+              resval: "0"
+            }
+            { bits: "5",
+              name: "ECC_EN",
+              desc: '''
+                Region is ECC enabled.
               ''',
               resval: "0"
             }
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index 00f4541..e9de226 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -516,6 +516,7 @@
   assign region_cfgs[MpRegions].prog_en.q = reg2hw.default_region.prog_en.q;
   assign region_cfgs[MpRegions].erase_en.q = reg2hw.default_region.erase_en.q;
   assign region_cfgs[MpRegions].scramble_en.q = reg2hw.default_region.scramble_en.q;
+  assign region_cfgs[MpRegions].ecc_en.q = reg2hw.default_region.ecc_en.q;
 
   //////////////////////////////////////
   // Info partition protection configuration
@@ -591,6 +592,7 @@
     // flash phy interface
     .req_o(flash_o.req),
     .scramble_en_o(flash_o.scramble_en),
+    .ecc_en_o(flash_o.ecc_en),
     .rd_o(flash_o.rd),
     .prog_o(flash_o.prog),
     .pg_erase_o(flash_o.pg_erase),
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 826ba75..93243a8 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
@@ -140,7 +140,8 @@
     rd_en:       1'b1,
     prog_en:     1'b0,
     erase_en:    1'b0,
-    scramble_en: 1'b0  // TBD, update to 1 once tb supports ECC
+    scramble_en: 1'b0,
+    ecc_en:      1'b0  // TBD, update to 1 once tb supports ECC
   };
 
   parameter info_page_cfg_t CfgAllowReadErase = '{
@@ -148,7 +149,8 @@
     rd_en:       1'b1,
     prog_en:     1'b0,
     erase_en:    1'b1,
-    scramble_en: 1'b0  // TBD, update to 1 once tb supports ECC
+    scramble_en: 1'b0,
+    ecc_en:      1'b0  // TBD, update to 1 once tb supports ECC
   };
 
   parameter info_page_attr_t HwInfoPageAttr[HwInfoRules] = '{
@@ -180,6 +182,7 @@
                  prog_en:     1'b0,
                  erase_en:    1'b1,
                  scramble_en: 1'b0,
+                 ecc_en:      1'b0,
                  base:        '0,
                  size:        '{default:'1}
                 }
@@ -235,6 +238,7 @@
   typedef struct packed {
     logic                 req;
     logic                 scramble_en;
+    logic                 ecc_en;
     logic                 rd;
     logic                 prog;
     logic                 pg_erase;
@@ -253,6 +257,7 @@
   parameter flash_req_t FLASH_REQ_DEFAULT = '{
     req:         1'b0,
     scramble_en: 1'b0,
+    ecc_en:      1'b0,
     rd:          1'b0,
     prog:        1'b0,
     pg_erase:    1'b0,
diff --git a/hw/ip/flash_ctrl/rtl/flash_mp.sv b/hw/ip/flash_ctrl/rtl/flash_mp.sv
index 5e174f0..a0a8690 100644
--- a/hw/ip/flash_ctrl/rtl/flash_mp.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_mp.sv
@@ -41,6 +41,7 @@
   output logic rd_o,
   output logic prog_o,
   output logic scramble_en_o,
+  output logic ecc_en_o,
   output logic pg_erase_o,
   output logic bk_erase_o,
   input rd_done_i,
@@ -71,10 +72,12 @@
   logic data_pg_erase_en;
   logic data_bk_erase_en;
   logic data_scramble_en;
+  logic data_ecc_en;
   logic info_rd_en;
   logic info_prog_en;
   logic info_erase_en;
   logic info_scramble_en;
+  logic info_ecc_en;
 
   // Memory protection handling for hardware interface
   logic hw_sel;
@@ -175,6 +178,7 @@
   assign data_pg_erase_en = data_en & pg_erase_i      & data_region_cfg.erase_en.q;
   assign data_bk_erase_en = data_en & bk_erase_i      & |bk_erase_en;
   assign data_scramble_en = data_en & (rd_i | prog_i) & data_region_cfg.scramble_en.q;
+  assign data_ecc_en      = data_en & (rd_i | prog_i) & data_region_cfg.ecc_en.q;
 
 
   assign invalid_data_txn = req_i & data_part_sel &
@@ -227,6 +231,7 @@
   assign info_prog_en     = info_en & prog_i          & page_cfg.prog_en.q;
   assign info_erase_en    = info_en & pg_erase_i      & page_cfg.erase_en.q;
   assign info_scramble_en = info_en & (rd_i | prog_i) & page_cfg.scramble_en.q;
+  assign info_ecc_en      = info_en & (rd_i | prog_i) & page_cfg.ecc_en.q;
 
   // check for invalid transactions
   assign invalid_info_txn = req_i & info_part_sel &
@@ -241,6 +246,7 @@
   assign pg_erase_o    = req_i & (data_pg_erase_en | info_erase_en);
   assign bk_erase_o    = req_i & data_bk_erase_en;
   assign scramble_en_o = req_i & (data_scramble_en | info_scramble_en);
+  assign ecc_en_o      = req_i & (data_ecc_en | info_ecc_en);
   assign req_o         = rd_o | prog_o | pg_erase_o | bk_erase_o;
 
   logic txn_err;
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy.sv b/hw/ip/flash_ctrl/rtl/flash_phy.sv
index 4c5969c..750cddd 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy.sv
@@ -105,7 +105,7 @@
 
   // Generate host scramble_en indication, broadcasted to all banks
   localparam int TotalRegions = MpRegions + 1;
-  logic host_scramble_en;
+  logic host_scramble_en, host_ecc_en;
   data_region_attr_t region_attrs [TotalRegions];
   mp_region_cfg_t region_cfg, unused_cfg;
 
@@ -128,8 +128,9 @@
   // most attributes are unused
   assign unused_cfg = region_cfg;
 
-  // only scramble attributes are looked at
+  // only scramble/ecc attributes are looked at
   assign host_scramble_en = region_cfg.scramble_en.q;
+  assign host_ecc_en = region_cfg.ecc_en.q;
 
   for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_flash_banks
 
@@ -163,10 +164,12 @@
       .rst_ni,
       .req_i(ctrl_req),
       .scramble_en_i(flash_ctrl_i.scramble_en),
+      .ecc_en_i(flash_ctrl_i.ecc_en),
       // host request must be suppressed if response fifo cannot hold more
       // otherwise the flash_phy_core and flash_phy will get out of sync
       .host_req_i(host_req),
       .host_scramble_en_i(host_scramble_en),
+      .host_ecc_en_i(host_ecc_en),
       .host_addr_i(host_addr_i[0 +: BusBankAddrW]),
       .rd_i(flash_ctrl_i.rd),
       .prog_i(flash_ctrl_i.prog),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index 481e52a..1793443 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -17,9 +17,11 @@
   input                              rst_ni,
   input                              host_req_i,   // host request - read only
   input                              host_scramble_en_i,
+  input                              host_ecc_en_i,
   input [BusBankAddrW-1:0]           host_addr_i,
   input                              req_i,        // controller request
   input                              scramble_en_i,
+  input                              ecc_en_i,
   input                              rd_i,
   input                              prog_i,
   input                              pg_erase_i,
@@ -83,6 +85,7 @@
   logic [BusBankAddrW-1:0] muxed_addr;
   flash_ctrl_pkg::flash_part_e muxed_part;
   logic muxed_scramble_en;
+  logic muxed_ecc_en;
 
   // entire read stage is idle, inclusive of all stages
   logic rd_stage_idle;
@@ -219,6 +222,7 @@
   assign muxed_addr = host_sel ? host_addr_i : addr_i;
   assign muxed_part = host_sel ? flash_ctrl_pkg::FlashPartData : part_i;
   assign muxed_scramble_en = host_sel ? host_scramble_en_i : scramble_en_i;
+  assign muxed_ecc_en = host_sel ? host_ecc_en_i : ecc_en_i;
   assign rd_done_o = ctrl_rsp_vld & rd_i;
   assign prog_done_o = ctrl_rsp_vld & prog_i;
   assign erase_done_o = ctrl_rsp_vld & (pg_erase_i | bk_erase_i);
@@ -240,6 +244,7 @@
     .rst_ni,
     .req_i(reqs[PhyRead]),
     .descramble_i(muxed_scramble_en),
+    .ecc_i(muxed_ecc_en),
     .prog_i(reqs[PhyProg]),
     .pg_erase_i(reqs[PhyPgErase]),
     .bk_erase_i(reqs[PhyBkErase]),
@@ -287,6 +292,7 @@
       .rst_ni,
       .req_i(reqs[PhyProg]),
       .scramble_i(muxed_scramble_en),
+      .ecc_i(muxed_ecc_en),
       .sel_i(addr_i[0 +: WordSelW]),
       .data_i(prog_data_i),
       .last_i(prog_last_i),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
index 4d3b8c9..6937548 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
@@ -72,6 +72,7 @@
   typedef struct packed {
     logic [BankAddrW-1:0] addr;
     logic descramble;
+    logic ecc;
   } rd_attr_t;
 
   // Flash Operations Supported
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
index caeac92..189e52a 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
@@ -27,6 +27,7 @@
   input rst_ni,
   input req_i,
   input scramble_i,
+  input ecc_i,
   input [WordSelW-1:0] sel_i,
   input [BusWidth-1:0] data_i,
   input last_i,
@@ -239,7 +240,7 @@
   );
 
   // pad the remaining bits to '0', this effectively "programs" them.
-  assign data_o = scramble_i ? FullDataWidth'(ecc_data) : FullDataWidth'(packed_data);
+  assign data_o = ecc_i ? FullDataWidth'(ecc_data) : FullDataWidth'(packed_data);
 
   /////////////////////////////////
   // Assertions
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
index ef8b242..d0813df 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
@@ -33,6 +33,7 @@
   // interface with arbitration unit
   input req_i,
   input descramble_i,
+  input ecc_i,
   input prog_i,
   input pg_erase_i,
   input bk_erase_i,
@@ -274,6 +275,7 @@
       alloc_q <= alloc;
       rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
       rd_attrs.descramble <= descramble_i;
+      rd_attrs.ecc <= ecc_i;
     end else if (rd_done) begin
       rd_busy <= 1'b0;
     end
@@ -320,6 +322,7 @@
     .syndrome_o(),
     .err_o({ecc_err, ecc_single_err})
   );
+
   assign unused_err = ecc_single_err;
 
   // If data needs to be de-scrambled and has not been erased, pass through ecc decoder.
@@ -327,9 +330,9 @@
   // Likewise, ecc error is only observed if the data needs to be de-scrambled and has not been
   // erased.
   // rd_done signal below is duplicated (already in data_erased) to show clear intent of the code.
-  assign data_int = (rd_done && rd_attrs.descramble && !data_erased) ? data_ecc_chk :
-                                                                       data_i[DataWidth-1:0];
-  assign data_err = (rd_done && rd_attrs.descramble && !data_erased) ? ecc_err : 1'b0;
+  assign data_int = (rd_done && rd_attrs.ecc && !data_erased) ? data_ecc_chk :
+                                                                data_i[DataWidth-1:0];
+  assign data_err = (rd_done && rd_attrs.ecc && !data_erased) ? ecc_err : 1'b0;
 
   /////////////////////////////////
   // De-scrambling stage