* [PATCH v2 1/3] dt-bindings: net: wireless: intel,iwlwifi: add binding
2026-05-04 9:53 [PATCH v2 0/3] wifi: iwlwifi: add Device Tree hardware integration information Avinash Bhatt
@ 2026-05-04 9:53 ` Avinash Bhatt
2026-05-05 9:15 ` Krzysztof Kozlowski
2026-05-04 9:53 ` [PATCH v2 2/3] wifi: iwlwifi: dt: add Device Tree BIOS configuration infrastructure Avinash Bhatt
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Avinash Bhatt @ 2026-05-04 9:53 UTC (permalink / raw)
To: devicetree, linux-wireless
Cc: robh, krzk+dt, conor+dt, johannes, miriam.rachel.korenblit,
linux-kernel, kobi.guetta, emmanuel.grumbach, avinash.bhatt
Add a devicetree schema binding for Intel discrete Wi-Fi 7 BE200 PCIe
adapters.
The binding documents OEM platform configuration properties for
platforms that use Device Tree instead of platform firmware
methods. All properties mirror the existing equivalents in
structure and semantics, covering SAR power limits (intel,wrds),
6 GHz AP type support (intel,uats), static power limit
(intel,splc), channel puncturing (intel,wcpe), 320 MHz per-MCC
enablement (intel,wbem), ETSI SRD channel configuration
(intel,srd), 6-7 GHz UHB country enable bitmask (intel,6e-uhb),
and additional regulatory override properties.
Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
---
.../bindings/net/wireless/intel,iwlwifi.yaml | 430 ++++++++++++++++++
1 file changed, 430 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/wireless/intel,iwlwifi.yaml
diff --git a/Documentation/devicetree/bindings/net/wireless/intel,iwlwifi.yaml b/Documentation/devicetree/bindings/net/wireless/intel,iwlwifi.yaml
new file mode 100644
index 000000000000..210063c6183d
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/intel,iwlwifi.yaml
@@ -0,0 +1,430 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (c) 2026 Intel Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/wireless/intel,iwlwifi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel iwlwifi PCIe Wi-Fi devices
+
+maintainers:
+ - Avinash Bhatt <avinash.bhatt@intel.com>
+
+description:
+ Intel iwlwifi IEEE 802.11be discrete Wi-Fi adapters connected over PCIe.
+
+properties:
+ compatible:
+ enum:
+ - pci8086,272b
+
+ reg:
+ maxItems: 1
+
+ intel,wrds:
+ description: |
+ Wi-Fi Regulatory Domain Settings (WRDS). SAR (Specific Absorption Rate)
+ transmit power limits per antenna chain and frequency subband. Values
+ are 8-bit unsigned in units of 0.125 dBm.
+
+ Revision 3 layout: 4 chains x 12 subbands = 50 cells total.
+ Chain A and Chain B are the two physical antenna paths; CDB Chain A
+ and CDB Chain B carry separate limits for simultaneous dual-band
+ operation.
+
+ Header (2 cells):
+ [0] revision - structure revision, must be 0x03
+ [1] mode - bit 0: 0 = SAR disabled, 1 = SAR enabled;
+ bits [8:1]: set to 0
+
+ Followed by 4 chains in order: chain_a, chain_b, cdb_chain_a,
+ cdb_chain_b, each containing 12 subband values:
+
+ Subband index to frequency range mapping:
+ [0] 2.4 GHz ch 1-13 (2412-2472 MHz)
+ [1] 5 GHz ch 36-64 (5180-5320 MHz, UNII-1/2)
+ [2] 5 GHz ch 68-96 (5340-5480 MHz, UNII-2)
+ [3] 5 GHz ch 100-144 (5500-5720 MHz, UNII-2e)
+ [4] 5 GHz ch 149-188 (5745-5940 MHz, UNII-3/4)
+ [5] 6 GHz ch 1-45 (5955-6175 MHz, UNII-5 lower)
+ [6] 6 GHz ch 49-93 (6195-6415 MHz, UNII-5 upper)
+ [7] 6 GHz ch 97-115 (6435-6525 MHz, UNII-6)
+ [8] 6 GHz ch 117-151 (6535-6705 MHz, UNII-7 lower)
+ [9] 6 GHz ch 153-183 (6715-6865 MHz, UNII-7 upper)
+ [10] 6 GHz ch 185-233 (6875-7115 MHz, UNII-8)
+ [11] 6 GHz ch 237-253 (7135-7215 MHz, UNII-9)
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - minItems: 50
+ maxItems: 50
+
+ intel,uats:
+ description: |
+ UHB (Ultra High Band / 6 GHz) AP Type Support (UATS). Per-country
+ enablement matrix for 6 GHz AP types. Uses byte array format
+ (DTS [ ... ] notation).
+
+ In the 6 GHz band, regulatory rules differ per country and per AP
+ type: AFC (Standard Power), LPI (Low Power Indoor), and VLP (Very
+ Low Power). This matrix encodes which AP types are permitted to
+ operate in each country.
+
+ Revision 1 layout (339 bytes total):
+ [0] revision - structure revision, must be 0x01
+ [1+] country_map - 338-byte matrix encoding AP type allowances
+ per country.
+
+ Countries are identified by their ISO 3166-1
+ alpha-2 code (two letters, A-Z each). The
+ matrix covers all 26x26 = 676 possible
+ two-letter combinations (AA..ZZ), most of
+ which are unused (set to 0x0).
+
+ Each country entry is 4 bits (a nibble). Two
+ entries are packed per byte: the low nibble
+ holds the even-indexed entry, the high nibble
+ holds the odd-indexed entry. For example,
+ byte value 0x53 means: entry[even]=0x3,
+ entry[odd]=0x5.
+
+ The matrix is stored column-major by first
+ letter: all 26 second-letter variants for
+ first letter 'A' occupy bytes [0..12], then
+ first letter 'B' occupies bytes [13..25],
+ and so on for all 26 first letters.
+ 26 columns x 13 bytes = 338 bytes total.
+
+ Each 4-bit nibble encodes AP type allowances
+ for one country:
+ bit 0: AFC (Standard Power AP) allowed
+ bit 1: VLP (Very Low Power AP) allowed
+ bit 2: LPI (Low Power Indoor AP) allowed
+ bit 3: reserved, must be 0
+
+ Note: each bit is only effective when the
+ corresponding control bit in intel,6e-uhb
+ is also set (bit 30 for AFC, bit 29
+ for VLP, bit 31 for LPI country-by-country
+ mode).
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint8-array
+ - minItems: 339
+ maxItems: 339
+
+ intel,srd:
+ description: |
+ ETSI 5.8 GHz SRD (Short Range Device) channel configuration.
+ Controls how the driver handles the 5725-5875 MHz (5.8 GHz) SRD
+ channels in ETSI regulatory domains.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] value - channel configuration:
+ 0 = active scan permitted (default behaviour)
+ 1 = passive scan only; device may associate and
+ transfer data but must not transmit probe
+ requests on SRD channels
+ 2 = SRD channels fully disabled; the device must
+ not scan, associate, or operate on any of the
+ 5725-5875 MHz SRD channels
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - enum: [0, 1, 2]
+
+ intel,6e-uhb:
+ description: |
+ 6-7 GHz Ultra-High Band (UHB) per-country enable bitmask.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] bitmap - UHB enablement control:
+ bit 0: override control; 0 = use device defaults,
+ 1 = force-disable all countries not
+ explicitly enabled in bits 1-25
+ bits 1-25: per-country/region enable flags:
+ bit 1 = USA
+ bit 2 = Rest of World (ROW)
+ bit 3 = EU
+ bit 4 = South Korea
+ bit 5 = Brazil
+ bit 6 = Chile
+ bit 7 = Japan
+ bit 8 = Canada
+ bit 9 = Morocco
+ bit 10 = Mongolia
+ bit 11 = Malaysia
+ bit 12 = Saudi Arabia
+ bit 13 = Mexico
+ bit 14 = Nigeria
+ bit 15 = Thailand
+ bit 16 = Singapore
+ bit 17 = Taiwan
+ bit 18 = South Africa
+ bit 19 = Philippines
+ bit 20 = Serbia
+ bit 21 = Indonesia
+ bit 22 = Azerbaijan
+ bit 23 = Paraguay
+ bit 24 = Vietnam
+ bit 25 = India
+ bit 26: reserved, must be 0
+ bit 27: enable VLP active scan, SoftAP, and
+ P2P-GO operation in Japan
+ bit 28: reserved, must be 0
+ bit 29: enable VLP (Very Low Power) mode per
+ country-by-country table
+ bit 30: enable AFC (Standard Power) mode per
+ country-by-country table
+ bit 31: LPI override mode; 0 = use grouping
+ mechanism, 1 = use country-by-country table
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+ intel,regulatory-special:
+ description: |
+ Regulatory Special Configurations.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] bitmap - configuration flags:
+ bits 0-3: reserved, must be 0
+ bit 4 = Australia UHB extension
+ bits 5-31: reserved, must be 0
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+ intel,activate-channel:
+ description: |
+ Indoor channel activation bitmask. Sets specific frequency bands to
+ active (rather than passive or disabled) when the platform is
+ confirmed to be operating indoors.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] bitmap - per-region indoor activation flags:
+ bit 0 = enable EU U-NII-1 (5.2 GHz) for indoors only
+ bit 1 = enable Japan U-NII-1 (5.2 GHz) for indoors only
+ bit 2 = enable China Mainland U-NII-1 (5.2 GHz)
+ for indoors only
+ bit 3 = enable USA U-NII-4 (5.9 GHz) for indoors only
+ bit 4 = enable WW U-NII-1 (5.2 GHz) for indoors in any
+ country where the band is permitted
+ bit 5 = enable Canada U-NII-4 (5.9 GHz) for indoors only
+ bit 6 = enable USA + Canada + WW U-NII-4 (5.9 GHz) for
+ indoors only
+ bits 7-31: reserved, must be 0
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+ intel,force-disable-channels:
+ description: |
+ Selective Wi-Fi band force-disable bitmask. Allows the platform to
+ permanently disable specific frequency bands regardless of regulatory
+ domain.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] bitmap - per-band force-disable flags:
+ bit 0 = force disable 2.4 GHz (channels 1-13)
+ bit 1 = force disable 5.2 GHz (channels 36-48)
+ bit 2 = force disable 5.3 GHz (channels 52-64)
+ bit 3 = force disable 5.5 GHz (channels 100-144)
+ bit 4 = force disable 5.8 GHz (channels 149-165)
+ bit 5 = force disable 5.9 GHz (channels 169-177)
+ bit 6 = force disable 6.2 GHz (channels 1-93)
+ bit 7 = force disable 6.5 GHz (channels 97-113)
+ bit 8 = force disable 6.6 GHz (channels 117-153)
+ bit 9 = force disable 6.8 GHz (channels 157-185)
+ bit 10 = force disable 7.0 GHz (channels 185-233)
+ bits 11-31: reserved, must be 0
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+ intel,11be:
+ description: |
+ 802.11be (Wi-Fi 7) per-country enable bitmask. Controls whether
+ 802.11be operation is permitted in specific countries.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] bitmap - per-country enable flags:
+ bit 0 = enable 802.11be in China (CB/CN)
+ bit 1 = enable 802.11be in South Korea
+ bits 2-31: reserved, must be 0
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+ intel,splc:
+ description: |
+ Wi-Fi Static Power Limit Capabilities (SPLC). Sets the platform thermal
+ power limit for the Wi-Fi core in mW. Omit this property entirely if
+ no platform power limit applies; the device will use its certified
+ maximum in that case.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] power_limit - maximum platform power budget in mW, must be
+ non-zero (a zero value is equivalent to omitting
+ the property)
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - minimum: 1
+
+ intel,wcpe:
+ description: |
+ Wi-Fi Channel Puncturing Enablement (WCPE). Enables 802.11be channel
+ puncturing for specific regulatory domains.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] puncturing - per-country enable bitmask:
+ bit 0: 1 = channel puncturing enabled for USA
+ bit 1: 1 = channel puncturing enabled for Canada
+ bits 2-31: reserved, must be 0
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+ intel,wbem:
+ description: |
+ Wi-Fi 320 MHz Bandwidth Enablement per MCC (WBEM). Controls whether
+ 320 MHz operation is permitted in specific countries.
+
+ Layout (2 cells):
+ [0] revision - structure revision, must be 0x00
+ [1] wifi320mhz_mcc - per-country enable bitmask:
+ bit 0: 1 = 320 MHz enabled for Japan
+ bit 1: 1 = 320 MHz enabled for South Korea
+ bits 2-31: reserved, must be 0
+
+ Each bit takes effect only if the installed
+ module is certified for 320 MHz in that country.
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - items:
+ - const: 0
+ - {}
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ /* ARM64 platform with Intel Wi-Fi 7 BE200 as discrete PCIe device */
+ pcie {
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ bus-range = <0x01 0xff>;
+
+ wifi@0 {
+ compatible = "pci8086,272b";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ /*
+ * Wi-Fi Regulatory Domain Settings (SAR power limits).
+ * Revision 3: 4 chains x 12 subbands = 50 cells total.
+ * Layout: revision, mode, then 4 x chain[12].
+ */
+ intel,wrds = <
+ 0x03 0x01
+ /* Chain A: 12 subbands */
+ 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38
+ /* Chain B: 12 subbands */
+ 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38 0x38
+ /* CDB Chain A: 12 subbands */
+ 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c
+ /* CDB Chain B: 12 subbands */
+ 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3c
+ >;
+
+ /*
+ * Static Power Limit: 4500 mW cap on this platform.
+ * 2 u32 cells: revision, power_limit_mw.
+ */
+ intel,splc = <0x00 0x1194>;
+
+ /*
+ * Channel Puncturing: enabled for USA and Canada.
+ * 2 u32 cells: revision, puncturing bitmask (bits 0+1).
+ */
+ intel,wcpe = <0x00 0x03>;
+
+ /*
+ * 320 MHz per MCC: Japan and South Korea enabled.
+ * 2 u32 cells: revision, wifi320mhz_mcc.
+ */
+ intel,wbem = <0x00 0x03>;
+
+ /* OEM regulatory configuration properties. */
+ intel,srd = <0x00 1>; /* revision=0, passive scan only */
+ intel,activate-channel = <0x00 0x01>; /* EU indoors */
+ intel,force-disable-channels = <0x00 0x00>; /* revision=0 */
+ intel,6e-uhb = <0x00 0x06>; /* revision=0, USA+ROW */
+
+ /*
+ * UHB AP Type Support (6 GHz country matrix).
+ * Byte array: revision (0x01), then
+ * 338 bytes of the 26x13 country enable map (all zeros
+ * in this example = no countries enabled).
+ */
+ intel,uats = [01
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00];
+ };
+ };
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/3] wifi: iwlwifi: dt: add Device Tree BIOS configuration infrastructure
2026-05-04 9:53 [PATCH v2 0/3] wifi: iwlwifi: add Device Tree hardware integration information Avinash Bhatt
2026-05-04 9:53 ` [PATCH v2 1/3] dt-bindings: net: wireless: intel,iwlwifi: add binding Avinash Bhatt
@ 2026-05-04 9:53 ` Avinash Bhatt
2026-05-05 9:18 ` Krzysztof Kozlowski
2026-05-04 9:53 ` [PATCH v2 3/3] wifi: iwlwifi: dt: use Device Tree as fallback BIOS configuration source Avinash Bhatt
2026-05-05 9:19 ` [PATCH v2 0/3] wifi: iwlwifi: add Device Tree hardware integration information Krzysztof Kozlowski
3 siblings, 1 reply; 7+ messages in thread
From: Avinash Bhatt @ 2026-05-04 9:53 UTC (permalink / raw)
To: devicetree, linux-wireless
Cc: robh, krzk+dt, conor+dt, johannes, miriam.rachel.korenblit,
linux-kernel, kobi.guetta, emmanuel.grumbach, avinash.bhatt
On platforms that use Device Tree and do not provide UEFI variables or
ACPI methods, discrete Intel Wi-Fi adapters have no way to receive BIOS
configuration. Add Device Tree as a supported configuration source for
SAR limits and 6 GHz AP type support, with stub hooks for TAS and
per-platform antenna gain tables.
DT support is gated on CONFIG_OF and is a no-op on x86. BIOS_SOURCE_DT
is added to enum bios_source to track the configuration origin.
Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
---
drivers/net/wireless/intel/iwlwifi/Makefile | 1 +
drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 5 +-
.../wireless/intel/iwlwifi/fw/api/nvm-reg.h | 4 +-
drivers/net/wireless/intel/iwlwifi/fw/dt.c | 321 ++++++++++++++++++
drivers/net/wireless/intel/iwlwifi/fw/dt.h | 123 +++++++
.../wireless/intel/iwlwifi/fw/regulatory.h | 3 +-
6 files changed, 451 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/dt.c
create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/dt.h
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 941257b811b4..445c8a26b6bd 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -38,6 +38,7 @@ iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
iwlwifi-$(CONFIG_IWLMLD) += fw/smem.o fw/init.o
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
iwlwifi-$(CONFIG_EFI) += fw/uefi.o
+iwlwifi-$(CONFIG_OF) += fw/dt.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += fw/debugfs.o
iwlwifi-objs += $(iwlwifi-m)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index 51a57e57de7a..45eb35ffb637 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2023, 2025 Intel Corporation
+ * Copyright (C) 2018-2023, 2025-2026 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@@ -111,9 +111,6 @@
#define ACPI_PPAG_WIFI_DATA_SIZE_V3 ((ACPI_PPAG_NUM_CHAINS * \
ACPI_PPAG_NUM_BANDS_V3) + 2)
-#define IWL_SAR_ENABLE_MSK BIT(0)
-#define IWL_REDUCE_POWER_FLAGS_POS 1
-
/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */
#define UEFI_WIFI_GUID_UNLOCKED 0
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 443a9a416325..39289bf3a193 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -495,11 +495,13 @@ struct iwl_tas_config_cmd_v2_v4 {
* @BIOS_SOURCE_NONE: BIOS source is not defined
* @BIOS_SOURCE_ACPI: BIOS source is ACPI
* @BIOS_SOURCE_UEFI: BIOS source is UEFI
+ * @BIOS_SOURCE_DT: BIOS source is Device Tree
*/
enum bios_source {
BIOS_SOURCE_NONE,
BIOS_SOURCE_ACPI,
BIOS_SOURCE_UEFI,
+ BIOS_SOURCE_DT,
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dt.c b/drivers/net/wireless/intel/iwlwifi/fw/dt.c
new file mode 100644
index 000000000000..4f3d098204f0
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dt.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2026 Intel Corporation
+ */
+#include <linux/of.h>
+#include "iwl-drv.h"
+#include "iwl-debug.h"
+#include "fw/runtime.h"
+#include "fw/regulatory.h"
+#include "dt.h"
+
+/* DT property names */
+#define IWL_DT_PROP_WRDS "intel,wrds"
+#define IWL_DT_PROP_UATS "intel,uats"
+#define IWL_DT_PROP_SPLC "intel,splc"
+#define IWL_DT_PROP_WBEM "intel,wbem"
+#define IWL_DT_PROP_WCPE "intel,wcpe"
+#define IWL_DT_WCPE_USA_EN BIT(0)
+#define IWL_DT_WCPE_CANADA_EN BIT(1)
+#define IWL_DT_WCPE_MASK (IWL_DT_WCPE_USA_EN | \
+ IWL_DT_WCPE_CANADA_EN)
+#define IWL_DT_PROP_SRD "intel,srd"
+#define IWL_DT_PROP_6E_UHB "intel,6e-uhb"
+#define IWL_DT_PROP_REG_SPECIAL "intel,regulatory-special"
+#define IWL_DT_PROP_ACTIVATE_CH "intel,activate-channel"
+#define IWL_DT_PROP_FORCE_DISABLE_CH "intel,force-disable-channels"
+#define IWL_DT_PROP_11BE "intel,11be"
+
+/* Supported revision values for each DT property */
+#define IWL_DT_WRDS_REVISION 3
+#define IWL_DT_UATS_REVISION 1
+
+/* SAR layout for "intel,wrds" revision 3 (mirrors ACPI_SAR_NUM_CHAINS_REV2
+ * and UEFI_SAR_SUB_BANDS_NUM_REV3): 4 chains x 12 subbands
+ */
+#define IWL_DT_WRDS_NUM_CHAINS 4
+#define IWL_DT_WRDS_NUM_SUBBANDS 12
+/* Total cell count for "intel,wrds" property: 2-cell header + SAR data */
+#define IWL_DT_WRDS_MAX_CELLS \
+ (2 + IWL_DT_WRDS_NUM_CHAINS * IWL_DT_WRDS_NUM_SUBBANDS)
+
+/**
+ * iwl_dt_get_wrds_table - read SAR power limits from DT "intel,wrds" property
+ * @fwrt: firmware runtime context
+ *
+ * Reads per-chain, per-subband SAR power limits from the "intel,wrds"
+ * Device Tree property and populates the SAR profile.
+ *
+ * Return: 0 on success, -ENOENT if the property or DT node is absent,
+ * or a negative error code for malformed data.
+ */
+int iwl_dt_get_wrds_table(struct iwl_fw_runtime *fwrt)
+{
+ struct device_node *node = dev_of_node(fwrt->dev);
+ u32 buf[IWL_DT_WRDS_MAX_CELLS];
+ u8 num_chains, num_subbands;
+ int ret;
+
+ if (!node)
+ return -ENOENT;
+
+ ret = of_property_read_u32_array(node, IWL_DT_PROP_WRDS, buf,
+ IWL_DT_WRDS_MAX_CELLS);
+ if (ret) {
+ IWL_DEBUG_RADIO(fwrt, "WRDS DT: read failed (%d)\n", ret);
+ return ret;
+ }
+
+ if (buf[0] != IWL_DT_WRDS_REVISION) {
+ IWL_DEBUG_RADIO(fwrt,
+ "WRDS DT: revision %u not supported (only %u)\n",
+ buf[0], IWL_DT_WRDS_REVISION);
+ return -EINVAL;
+ }
+
+ num_chains = IWL_DT_WRDS_NUM_CHAINS;
+ num_subbands = IWL_DT_WRDS_NUM_SUBBANDS;
+
+ IWL_DEBUG_RADIO(fwrt,
+ "Reading WRDS from Device Tree (revision %u, %u chains, %u subbands)\n",
+ buf[0], num_chains, num_subbands);
+
+ /* buf[1] bit 0 (IWL_SAR_ENABLE_MSK): enable SAR */
+
+ BUILD_BUG_ON(IWL_DT_WRDS_NUM_CHAINS > BIOS_SAR_MAX_CHAINS_PER_PROFILE);
+ BUILD_BUG_ON(IWL_DT_WRDS_NUM_SUBBANDS > BIOS_SAR_MAX_SUB_BANDS_NUM);
+
+ /* buf[2..]: chains[0..N-1] x subbands[0..M-1] in row-major order */
+ for (int i = 0; i < num_chains; i++) {
+ for (int j = 0; j < num_subbands; j++) {
+ u32 val = buf[2 + i * num_subbands + j];
+
+ if (val > U8_MAX) {
+ IWL_DEBUG_RADIO(fwrt,
+ "DT: WRDS OOB [%u][%u]=%u\n",
+ i, j, val);
+ return -EINVAL;
+ }
+ fwrt->sar_profiles[0].chains[i].subbands[j] = (u8)val;
+ }
+ }
+
+ if (buf[1] & IWL_SAR_ENABLE_MSK)
+ fwrt->sar_profiles[0].enabled = true;
+
+ return 0;
+}
+
+/**
+ * iwl_dt_get_uats_table - read UHB AP type support table from DT "intel,uats"
+ * @fwrt: firmware runtime context
+ *
+ * Reads the UHB AP type support table from the "intel,uats" Device Tree
+ * property and stores the MCC-to-AP-type map for use by the firmware command.
+ */
+void iwl_dt_get_uats_table(struct iwl_fw_runtime *fwrt)
+{
+ size_t map_size = sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_map);
+ struct device_node *node = dev_of_node(fwrt->dev);
+ const u8 *prop_data;
+ int len;
+
+ if (!node)
+ return;
+
+ prop_data = of_get_property(node, IWL_DT_PROP_UATS, &len);
+ if (!prop_data) {
+ IWL_DEBUG_FW(fwrt, "UATS DT: property absent\n");
+ return;
+ }
+
+ if (len != (int)(1 + map_size)) {
+ IWL_DEBUG_FW(fwrt, "UATS DT: bad length %d (expected %zu)\n",
+ len, 1 + map_size);
+ return;
+ }
+
+ if (prop_data[0] != IWL_DT_UATS_REVISION) {
+ IWL_DEBUG_FW(fwrt,
+ "UATS DT: revision %u not supported (expected %u)\n",
+ prop_data[0], IWL_DT_UATS_REVISION);
+ return;
+ }
+
+ IWL_DEBUG_FW(fwrt, "Reading UATS table from Device Tree\n");
+
+ /* prop_data[0]=revision, prop_data[1+]=26x13 MCC to AP type map */
+ memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_map, prop_data + 1, map_size);
+ fwrt->ap_type_cmd_valid = true;
+}
+IWL_EXPORT_SYMBOL(iwl_dt_get_uats_table);
+
+/*
+ * Mapping from DSM function index to Device Tree property name.
+ * Returns the DT property name for a given DSM function, or NULL if the
+ * function has no Device Tree representation.
+ */
+static const char *dsm_func_to_prop_name(enum iwl_dsm_funcs func)
+{
+ switch (func) {
+ case DSM_FUNC_DISABLE_SRD: return IWL_DT_PROP_SRD;
+ case DSM_FUNC_ENABLE_6E: return IWL_DT_PROP_6E_UHB;
+ case DSM_FUNC_REGULATORY_CONFIG: return IWL_DT_PROP_REG_SPECIAL;
+ case DSM_FUNC_ACTIVATE_CHANNEL: return IWL_DT_PROP_ACTIVATE_CH;
+ case DSM_FUNC_FORCE_DISABLE_CHANNELS:
+ return IWL_DT_PROP_FORCE_DISABLE_CH;
+ case DSM_FUNC_ENABLE_11BE: return IWL_DT_PROP_11BE;
+ default: return NULL;
+ }
+}
+
+/**
+ * iwl_dt_get_dsm - read one OEM DSM function value from Device Tree
+ * @fwrt: firmware runtime context
+ * @func: DSM function index (enum iwl_dsm_funcs)
+ * @value: output value
+ *
+ * Reads the DT property for @func on every call without caching.
+ * Unlike the ACPI/UEFI paths, the shared dsm_funcs_valid/dsm_values[]
+ * fields are not used here.
+ *
+ * Return: 0 on success, -ENOENT if no DT node, -EOPNOTSUPP if the function
+ * has no DT representation, -ENODATA if the property is absent,
+ * -EINVAL if the property revision is unsupported.
+ */
+int iwl_dt_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+ u32 *value)
+{
+ struct device_node *node = dev_of_node(fwrt->dev);
+ const char *prop;
+ u32 buf[2];
+
+ if (!node)
+ return -ENOENT;
+
+ if (func >= DSM_FUNC_NUM_FUNCS)
+ return -EOPNOTSUPP;
+
+ prop = dsm_func_to_prop_name(func);
+ if (!prop)
+ return -EOPNOTSUPP;
+
+ if (of_property_read_u32_array(node, prop, buf, ARRAY_SIZE(buf)))
+ return -ENODATA;
+
+ if (buf[0] != 0) {
+ IWL_DEBUG_RADIO(fwrt,
+ "DT: DSM func %d (%s) unsupported revision %u\n",
+ func, prop, buf[0]);
+ return -EINVAL;
+ }
+
+ if (fwrt->dsm_source == BIOS_SOURCE_NONE) {
+ fwrt->dsm_source = BIOS_SOURCE_DT;
+ fwrt->dsm_revision = 0;
+ }
+
+ *value = buf[1];
+ IWL_DEBUG_RADIO(fwrt, "DT: DSM func=%d (%s) val=%u\n",
+ func, prop, *value);
+ return 0;
+}
+
+/**
+ * iwl_dt_get_pwr_limit - read static platform power limit from DT "intel,splc"
+ * @fwrt: firmware runtime context
+ * @data: output power limit in mW
+ *
+ * Reads the 2-cell "intel,splc" DT property: [revision, power_limit_mw].
+ * Return: 0 on success, -ENOENT if absent, -EINVAL for unsupported revision.
+ */
+int iwl_dt_get_pwr_limit(struct iwl_fw_runtime *fwrt, u64 *data)
+{
+ struct device_node *node = dev_of_node(fwrt->dev);
+ u32 buf[2];
+ int ret;
+
+ if (!node)
+ return -ENOENT;
+
+ ret = of_property_read_u32_array(node, IWL_DT_PROP_SPLC,
+ buf, ARRAY_SIZE(buf));
+ if (ret)
+ return ret;
+
+ if (buf[0] != 0) {
+ IWL_DEBUG_RADIO(fwrt, "DT: splc unsupported revision %u\n",
+ buf[0]);
+ return -EINVAL;
+ }
+
+ *data = buf[1];
+ IWL_DEBUG_RADIO(fwrt, "DT: Read SPLC power limit %llu mW\n", *data);
+ return 0;
+}
+
+/**
+ * iwl_dt_get_wbem - read 320 MHz per-MCC enablement from DT "intel,wbem"
+ * @fwrt: firmware runtime context
+ * @data: output bitmask (bit 0 = Japan, bit 1 = South Korea)
+ *
+ * Reads the 2-cell "intel,wbem" DT property: [revision, wifi320mhz_mcc].
+ * Return: 0 on success, -ENOENT if absent, -EINVAL for unsupported revision.
+ */
+int iwl_dt_get_wbem(struct iwl_fw_runtime *fwrt, u32 *data)
+{
+ struct device_node *node = dev_of_node(fwrt->dev);
+ u32 buf[2];
+ int ret;
+
+ if (!node)
+ return -ENOENT;
+
+ ret = of_property_read_u32_array(node, IWL_DT_PROP_WBEM,
+ buf, ARRAY_SIZE(buf));
+ if (ret)
+ return ret;
+
+ if (buf[0] != 0) {
+ IWL_DEBUG_RADIO(fwrt, "DT: wbem unsupported revision %u\n",
+ buf[0]);
+ return -EINVAL;
+ }
+
+ *data = buf[1];
+ IWL_DEBUG_RADIO(fwrt, "DT: Read WBEM config 0x%x\n", *data);
+ return 0;
+}
+
+/**
+ * iwl_dt_get_puncturing - read channel puncturing config from DT "intel,wcpe"
+ * @fwrt: firmware runtime context
+ *
+ * Reads the 2-cell "intel,wcpe" DT property: [revision, puncturing_bitmap].
+ * Return: the bitmask (bit 0 = USA, bit 1 = Canada), or 0 if absent
+ * or revision unsupported.
+ */
+int iwl_dt_get_puncturing(struct iwl_fw_runtime *fwrt)
+{
+ struct device_node *node = dev_of_node(fwrt->dev);
+ u32 buf[2];
+ int ret;
+
+ if (!node)
+ return 0;
+
+ ret = of_property_read_u32_array(node, IWL_DT_PROP_WCPE,
+ buf, ARRAY_SIZE(buf));
+ if (ret)
+ return 0;
+
+ if (buf[0] != 0) {
+ IWL_DEBUG_RADIO(fwrt, "DT: wcpe unsupported revision %u\n",
+ buf[0]);
+ return 0;
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "DT: Read WCPE puncturing config 0x%x\n", buf[1]);
+ return buf[1] & IWL_DT_WCPE_MASK;
+}
+IWL_EXPORT_SYMBOL(iwl_dt_get_puncturing);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dt.h b/drivers/net/wireless/intel/iwlwifi/fw/dt.h
new file mode 100644
index 000000000000..01d8eef2babc
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dt.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/*
+ * Copyright (C) 2026 Intel Corporation
+ */
+#ifndef __iwl_fw_dt_h__
+#define __iwl_fw_dt_h__
+
+#include "fw/regulatory.h"
+
+/*
+ * Device Tree property parsing for Intel iwlwifi discrete Wi-Fi devices.
+ *
+ * On platforms without UEFI variables or ACPI methods, regulatory and
+ * power configuration can be supplied via Device Tree properties in the
+ * Wi-Fi PCIe device node. The following properties are supported:
+ *
+ * intel,wrds - SAR power limits (WRDS, revision 3)
+ * intel,uats - UHB AP type support table (UATS, revision 1)
+ * intel,splc - static platform power limit
+ * intel,wbem - 320 MHz per-MCC enablement
+ * intel,wcpe - channel puncturing enablement
+ * intel,srd - ETSI SRD channel configuration
+ * intel,6e-uhb - 6 GHz UHB country enable bitmask
+ * intel,regulatory-special - regulatory special configuration
+ * intel,activate-channel - indoor channel activation bitmask
+ * intel,force-disable-channels - band force-disable bitmask
+ * intel,11be - 802.11be per-country enable bitmask
+ *
+ * DT is the lowest-priority source: UEFI variables take precedence, then
+ * ACPI methods, and finally these DT properties.
+ */
+
+struct iwl_fw_runtime;
+
+#if IS_ENABLED(CONFIG_OF)
+
+/* Functions implemented in fw/dt.c */
+int iwl_dt_get_wrds_table(struct iwl_fw_runtime *fwrt);
+void iwl_dt_get_uats_table(struct iwl_fw_runtime *fwrt);
+int iwl_dt_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+ u32 *value);
+int iwl_dt_get_pwr_limit(struct iwl_fw_runtime *fwrt, u64 *data);
+int iwl_dt_get_wbem(struct iwl_fw_runtime *fwrt, u32 *data);
+int iwl_dt_get_puncturing(struct iwl_fw_runtime *fwrt);
+
+#else /* !CONFIG_OF */
+
+static inline int iwl_dt_get_wrds_table(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
+
+static inline void iwl_dt_get_uats_table(struct iwl_fw_runtime *fwrt) {}
+
+static inline int iwl_dt_get_dsm(struct iwl_fw_runtime *fwrt,
+ enum iwl_dsm_funcs func, u32 *value)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_pwr_limit(struct iwl_fw_runtime *fwrt, u64 *data)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_wbem(struct iwl_fw_runtime *fwrt, u32 *data)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_puncturing(struct iwl_fw_runtime *fwrt)
+{
+ return 0;
+}
+
+#endif /* CONFIG_OF */
+
+/*
+ * The following tables have no Device Tree implementation regardless of
+ * CONFIG_OF. Callers fall back gracefully when these return -ENOENT.
+ */
+static inline int iwl_dt_get_ppag_table(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_tas_table(struct iwl_fw_runtime *fwrt,
+ struct iwl_tas_data *data)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_ewrd_table(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_wgds_table(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_phy_filters(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_mcc(struct iwl_fw_runtime *fwrt, char *data)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_eckv(struct iwl_fw_runtime *fwrt, u32 *data)
+{
+ return -ENOENT;
+}
+
+static inline int iwl_dt_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *data)
+{
+ return -ENOENT;
+}
+
+#endif /* __iwl_fw_dt_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
index 6fffc032efd3..22c97c75b83c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2023-2025 Intel Corporation
+ * Copyright (C) 2023-2026 Intel Corporation
*/
#ifndef __fw_regulatory_h__
@@ -30,6 +30,7 @@
#define BIOS_GEO_MIN_PROFILE_NUM 3
#define IWL_SAR_ENABLE_MSK BIT(0)
+#define IWL_REDUCE_POWER_FLAGS_POS 1
/* PPAG gain value bounds in 1/8 dBm */
#define IWL_PPAG_MIN_LB -16
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread