.nvm_calib_ver = IWL3168_TX_POWER_VERSION,
        .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
        .dccm_len = IWL7265_DCCM_LEN,
+       .nvm_type = IWL_NVM_SDP,
 };
 
 const struct iwl_cfg iwl7265_2ac_cfg = {
 
        .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,       \
        .thermal_params = &iwl8000_tt_params,                           \
        .apmg_not_supported = true,                                     \
-       .ext_nvm = true,                                                \
+       .nvm_type = IWL_NVM_EXT,                                        \
        .dbgc_supported = true
 
 #define IWL_DEVICE_8000                                                        \
 
        .vht_mu_mimo_supported = true,                                  \
        .mac_addr_from_csr = true,                                      \
        .rf_id = true,                                                  \
-       .ext_nvm = true,                                                \
+       .nvm_type = IWL_NVM_EXT,                                        \
        .dbgc_supported = true
 
 const struct iwl_cfg iwl9160_2ac_cfg = {
 
        .use_tfh = true,                                                \
        .rf_id = true,                                                  \
        .gen2 = true,                                                   \
-       .ext_nvm = true,                                                \
+       .nvm_type = IWL_NVM_EXT,                                        \
        .dbgc_supported = true
 
 const struct iwl_cfg iwla000_2ac_cfg_hr = {
 
  * @NVM_SECTION_TYPE_REGULATORY: regulatory section
  * @NVM_SECTION_TYPE_CALIBRATION: calibration section
  * @NVM_SECTION_TYPE_PRODUCTION: production section
+ * @NVM_SECTION_TYPE_REGULATORY_SDP: regulatory section used by 3168 series
  * @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section
  * @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section
  * @NVM_MAX_NUM_SECTIONS: number of sections
        NVM_SECTION_TYPE_REGULATORY = 3,
        NVM_SECTION_TYPE_CALIBRATION = 4,
        NVM_SECTION_TYPE_PRODUCTION = 5,
+       NVM_SECTION_TYPE_REGULATORY_SDP = 8,
        NVM_SECTION_TYPE_MAC_OVERRIDE = 11,
        NVM_SECTION_TYPE_PHY_SKU = 12,
        NVM_MAX_NUM_SECTIONS = 13,
 
        IWL_LED_DISABLE,
 };
 
+/**
+ * enum iwl_nvm_type - nvm formats
+ * @IWL_NVM: the regular format
+ * @IWL_NVM_EXT: extended NVM format
+ * @IWL_NVM_SDP: NVM format used by 3168 series
+ */
+enum iwl_nvm_type {
+       IWL_NVM,
+       IWL_NVM_EXT,
+       IWL_NVM_SDP,
+};
+
 /*
  * This is the threshold value of plcp error rate per 100mSecs.  It is
  * used to set and check for the validity of plcp_delta.
  * @integrated: discrete or integrated
  * @gen2: a000 and on transport operation
  * @cdb: CDB support
- * @ext_nvm: extended NVM format
+ * @nvm_type: see &enum iwl_nvm_type
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
        const struct iwl_tt_params *thermal_params;
        enum iwl_device_family device_family;
        enum iwl_led_mode led_mode;
+       enum iwl_nvm_type nvm_type;
        u32 max_data_size;
        u32 max_inst_size;
        netdev_features_t features;
            use_tfh:1,
            gen2:1,
            cdb:1,
-           ext_nvm:1,
            dbgc_supported:1;
        u8 valid_tx_ant;
        u8 valid_rx_ant;
 
 #include "iwl-csr.h"
 
 /* NVM offsets (in words) definitions */
-enum wkp_nvm_offsets {
+enum nvm_offsets {
        /* NVM HW-Section offset (in words) definitions */
        SUBSYSTEM_ID = 0x0A,
        HW_ADDR = 0x15,
 
        /* NVM calibration section offset (in words) definitions */
        NVM_CALIB_SECTION = 0x2B8,
-       XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
+       XTAL_CALIB = 0x316 - NVM_CALIB_SECTION,
+
+       /* NVM REGULATORY -Section offset (in words) definitions */
+       NVM_CHANNELS_SDP = 0,
 };
 
 enum ext_nvm_offsets {
        u32 flags = IEEE80211_CHAN_NO_HT40;
        u32 last_5ghz_ht = LAST_5GHZ_HT;
 
-       if (cfg->ext_nvm)
+       if (cfg->nvm_type == IWL_NVM_EXT)
                last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
 
        if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
        int num_of_ch, num_2ghz_channels;
        const u8 *nvm_chan;
 
-       if (!cfg->ext_nvm) {
+       if (cfg->nvm_type != IWL_NVM_EXT) {
                num_of_ch = IWL_NUM_CHANNELS;
                nvm_chan = &iwl_nvm_channels[0];
                num_2ghz_channels = NUM_2GHZ_CHANNELS;
 static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
                       const __le16 *phy_sku)
 {
-       if (!cfg->ext_nvm)
+       if (cfg->nvm_type != IWL_NVM_EXT)
                return le16_to_cpup(nvm_sw + SKU);
 
        return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
 
 static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
 {
-       if (!cfg->ext_nvm)
+       if (cfg->nvm_type != IWL_NVM_EXT)
                return le16_to_cpup(nvm_sw + NVM_VERSION);
        else
                return le32_to_cpup((__le32 *)(nvm_sw +
 static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
                             const __le16 *phy_sku)
 {
-       if (!cfg->ext_nvm)
+       if (cfg->nvm_type != IWL_NVM_EXT)
                return le16_to_cpup(nvm_sw + RADIO_CFG);
 
        return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM));
 {
        int n_hw_addr;
 
-       if (!cfg->ext_nvm)
+       if (cfg->nvm_type != IWL_NVM_EXT)
                return le16_to_cpup(nvm_sw + N_HW_ADDRS);
 
        n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
                              struct iwl_nvm_data *data,
                              u32 radio_cfg)
 {
-       if (!cfg->ext_nvm) {
+       if (cfg->nvm_type != IWL_NVM_EXT) {
                data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
                data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
                data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
 {
        if (cfg->mac_addr_from_csr) {
                iwl_set_hw_address_from_csr(trans, data);
-       } else if (!cfg->ext_nvm) {
+       } else if (cfg->nvm_type != IWL_NVM_EXT) {
                const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
 
                /* The byte order is little endian 16 bit, meaning 214365 */
        u16 lar_config;
        const __le16 *ch_section;
 
-       if (!cfg->ext_nvm)
+       if (cfg->nvm_type != IWL_NVM_EXT)
                data = kzalloc(sizeof(*data) +
                               sizeof(struct ieee80211_channel) *
                               IWL_NUM_CHANNELS,
 
        data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
 
-       if (!cfg->ext_nvm) {
+       if (cfg->nvm_type != IWL_NVM_EXT) {
                /* Checking for required sections */
                if (!nvm_calib) {
                        IWL_ERR(trans,
                        kfree(data);
                        return NULL;
                }
+
+               ch_section = cfg->nvm_type == IWL_NVM_SDP ?
+                            ®ulatory[NVM_CHANNELS_SDP] :
+                            &nvm_sw[NVM_CHANNELS];
+
                /* in family 8000 Xtal calibration values moved to OTP */
                data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
                data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
                lar_enabled = true;
-               ch_section = &nvm_sw[NVM_CHANNELS];
        } else {
                u16 lar_offset = data->nvm_version < 0xE39 ?
                                 NVM_LAR_OFFSET_OLD :
        u32 flags = NL80211_RRF_NO_HT40;
        u32 last_5ghz_ht = LAST_5GHZ_HT;
 
-       if (cfg->ext_nvm)
+       if (cfg->nvm_type == IWL_NVM_EXT)
                last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
 
        if (ch_idx < NUM_2GHZ_CHANNELS &&
        int ch_idx;
        u16 ch_flags;
        u32 reg_rule_flags, prev_reg_rule_flags = 0;
-       const u8 *nvm_chan = cfg->ext_nvm ?
+       const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
                             iwl_ext_nvm_channels : iwl_nvm_channels;
        struct ieee80211_regdomain *regd;
        int size_of_regd;
        int center_freq, prev_center_freq = 0;
        int valid_rules = 0;
        bool new_rule;
-       int max_num_ch = cfg->ext_nvm ?
+       int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
                         IWL_NUM_CHANNELS_EXT : IWL_NUM_CHANNELS;
 
        if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
 
         * Enable LAR only if it is supported by the FW (TLV) &&
         * enabled in the NVM
         */
-       if (mvm->cfg->ext_nvm)
+       if (mvm->cfg->nvm_type == IWL_NVM_EXT)
                return nvm_lar && tlv_lar;
        else
                return tlv_lar;
 
        const __be16 *hw;
        const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku;
        bool lar_enabled;
+       int regulatory_type;
 
        /* Checking for required sections */
-       if (!mvm->trans->cfg->ext_nvm) {
+       if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
                if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
                    !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
                        IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
                        return NULL;
                }
        } else {
+               if (mvm->trans->cfg->nvm_type == IWL_NVM_SDP)
+                       regulatory_type = NVM_SECTION_TYPE_REGULATORY_SDP;
+               else
+                       regulatory_type = NVM_SECTION_TYPE_REGULATORY;
+
                /* SW and REGULATORY sections are mandatory */
                if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
-                   !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
+                   !mvm->nvm_sections[regulatory_type].data) {
                        IWL_ERR(mvm,
                                "Can't parse empty family 8000 OTP/NVM sections\n");
                        return NULL;
        hw = (const __be16 *)sections[mvm->cfg->nvm_hw_section_num].data;
        sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
        calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
-       regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
        mac_override =
                (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data;
        phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data;
 
+       regulatory = mvm->trans->cfg->nvm_type == IWL_NVM_SDP ?
+               (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data :
+               (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
+
        lar_enabled = !iwlwifi_mod_params.lar_disable &&
                      fw_has_capa(&mvm->fw->ucode_capa,
                                  IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
        IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
 
        /* Maximal size depends on NVM version */
-       if (!mvm->trans->cfg->ext_nvm)
+       if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT)
                max_section_size = IWL_MAX_NVM_SECTION_SIZE;
        else
                max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE;
                        break;
                }
 
-               if (!mvm->trans->cfg->ext_nvm) {
+               if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
                        section_size =
                                2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
                        section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
        struct ieee80211_regdomain *regd;
        char mcc[3];
 
-       if (mvm->cfg->ext_nvm) {
+       if (mvm->cfg->nvm_type == IWL_NVM_EXT) {
                tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
                                      IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
                nvm_lar = mvm->nvm_data->lar_enabled;