* Re: [PATCH v4 6/8] Bluetooth: hci_sync: Add NVMEM-backed BD address retrieval
From: Loic Poulain @ 2026-06-12 10:00 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, linux-mmc, devicetree,
linux-kernel, linux-arm-msm, linux-block, linux-wireless, ath10k,
linux-bluetooth, netdev, daniel, Bartosz Golaszewski
In-Reply-To: <sy2ofvdbcxspxtmfdavjvdz7oes5ieuep4znf4ayknmuwhrlgk@7lp3bkegaeif>
On Fri, Jun 12, 2026 at 11:11 AM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
>
> On Tue, Jun 09, 2026 at 09:52:31AM +0200, Loic Poulain wrote:
> > Some devices store the Bluetooth BD address in non-volatile
> > memory, which can be accessed through the NVMEM framework.
> > Similar to Ethernet or WiFi MAC addresses, add support for
> > reading the BD address from a 'local-bd-address' NVMEM cell.
> >
> > As with the device-tree provided BD address, add a quirk to
> > indicate whether a device or platform should attempt to read
> > the address from NVMEM when no valid in-chip address is present.
> > Also add a quirk to indicate if the address is stored in
> > big-endian byte order.
> >
> > Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> > Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> > ---
> > include/net/bluetooth/hci.h | 18 ++++++++++++++++++
> > net/bluetooth/hci_sync.c | 39 ++++++++++++++++++++++++++++++++++++++-
> > 2 files changed, 56 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> > index 572b1c620c5d653a1fe10b26c1b0ba33e8f4968f..7686466d1109253b0d75edeb5f6a99fb98ce4cc6 100644
> > --- a/include/net/bluetooth/hci.h
> > +++ b/include/net/bluetooth/hci.h
> > @@ -164,6 +164,24 @@ enum {
> > */
> > HCI_QUIRK_BDADDR_PROPERTY_BROKEN,
> >
> > + /* When this quirk is set, the public Bluetooth address
> > + * initially reported by HCI Read BD Address command
> > + * is considered invalid. The public BD Address can be
> > + * retrieved via a 'local-bd-address' NVMEM cell.
>
> Why do we need a quirk here? Can't we always assume that if there is an
> NVMEM cell, it contains a correct address, even if HCI command returned
> a seemingly-sensible one?
The pattern follows HCI_QUIRK_USE_BDADDR_PROPERTY, the quirk indicates
that the address returned by the HCI Read BD Address command is
invalid and should be overridden using a fwnode property. Without this
quirk, even a valid fwnode-provided address is ignored. So here this
is primarily done to align with that established behavior, although
whether that design choice is ideal is a good question.
This also raises the question of why an explicit HCI_QUIRK_USE_* flag
is required to allow reading from NVMEM when the controller-provided
address is known to be invalid, rather than attempting to use any
available backend (fwnode-prop or NVMEM). but this remains
consistent with the behavior established by the fwnode-based quirk.
So, I think these aspects could be revisited in a Bluetooth follow-up
series if there is interest in reworking the overall addr fallback
design.
Regards,
Loic
>
> > + *
> > + * This quirk can be set before hci_register_dev is called or
> > + * during the hdev->setup vendor callback.
> > + */
> > + HCI_QUIRK_USE_BDADDR_NVMEM,
> > +
> > + /* When this quirk is set, the Bluetooth Device Address provided by
> > + * the 'local-bd-address' NVMEM is stored in big-endian order.
> > + *
> > + * This quirk can be set before hci_register_dev is called or
> > + * during the hdev->setup vendor callback.
> > + */
> > + HCI_QUIRK_BDADDR_NVMEM_BE,
>
> Also, is this necessary? Are the devices which store the address in the
> wrong format in the NVMEM?
>
> > +
> > /* When this quirk is set, the duplicate filtering during
> > * scanning is based on Bluetooth devices addresses. To allow
> > * RSSI based updates, restart scanning if needed.
>
> --
> With best wishes
> Dmitry
^ permalink raw reply
* Re: [PATCH v4 7/8] Bluetooth: qca: Set NVMEM BD address quirks when address is invalid
From: Dmitry Baryshkov @ 2026-06-12 9:12 UTC (permalink / raw)
To: Loic Poulain
Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, linux-mmc, devicetree,
linux-kernel, linux-arm-msm, linux-block, linux-wireless, ath10k,
linux-bluetooth, netdev, daniel, Bartosz Golaszewski
In-Reply-To: <20260609-block-as-nvmem-v4-7-45712e6b22c6@oss.qualcomm.com>
On Tue, Jun 09, 2026 at 09:52:32AM +0200, Loic Poulain wrote:
> When the controller BD address is invalid (zero or default),
> set the NVMEM quirks to allow retrieving the address from a
> 'local-bd-address' NVMEM cell. The BD address is often stored
> alongside the WiFi MAC address in big-endian format, so also
> set the big-endian quirk.
Okay, this answers my question to the previous patch. We need to support
BE addresses.
>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> ---
> drivers/bluetooth/btqca.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v4 6/8] Bluetooth: hci_sync: Add NVMEM-backed BD address retrieval
From: Dmitry Baryshkov @ 2026-06-12 9:11 UTC (permalink / raw)
To: Loic Poulain
Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, linux-mmc, devicetree,
linux-kernel, linux-arm-msm, linux-block, linux-wireless, ath10k,
linux-bluetooth, netdev, daniel, Bartosz Golaszewski
In-Reply-To: <20260609-block-as-nvmem-v4-6-45712e6b22c6@oss.qualcomm.com>
On Tue, Jun 09, 2026 at 09:52:31AM +0200, Loic Poulain wrote:
> Some devices store the Bluetooth BD address in non-volatile
> memory, which can be accessed through the NVMEM framework.
> Similar to Ethernet or WiFi MAC addresses, add support for
> reading the BD address from a 'local-bd-address' NVMEM cell.
>
> As with the device-tree provided BD address, add a quirk to
> indicate whether a device or platform should attempt to read
> the address from NVMEM when no valid in-chip address is present.
> Also add a quirk to indicate if the address is stored in
> big-endian byte order.
>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> ---
> include/net/bluetooth/hci.h | 18 ++++++++++++++++++
> net/bluetooth/hci_sync.c | 39 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 56 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 572b1c620c5d653a1fe10b26c1b0ba33e8f4968f..7686466d1109253b0d75edeb5f6a99fb98ce4cc6 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -164,6 +164,24 @@ enum {
> */
> HCI_QUIRK_BDADDR_PROPERTY_BROKEN,
>
> + /* When this quirk is set, the public Bluetooth address
> + * initially reported by HCI Read BD Address command
> + * is considered invalid. The public BD Address can be
> + * retrieved via a 'local-bd-address' NVMEM cell.
Why do we need a quirk here? Can't we always assume that if there is an
NVMEM cell, it contains a correct address, even if HCI command returned
a seemingly-sensible one?
> + *
> + * This quirk can be set before hci_register_dev is called or
> + * during the hdev->setup vendor callback.
> + */
> + HCI_QUIRK_USE_BDADDR_NVMEM,
> +
> + /* When this quirk is set, the Bluetooth Device Address provided by
> + * the 'local-bd-address' NVMEM is stored in big-endian order.
> + *
> + * This quirk can be set before hci_register_dev is called or
> + * during the hdev->setup vendor callback.
> + */
> + HCI_QUIRK_BDADDR_NVMEM_BE,
Also, is this necessary? Are the devices which store the address in the
wrong format in the NVMEM?
> +
> /* When this quirk is set, the duplicate filtering during
> * scanning is based on Bluetooth devices addresses. To allow
> * RSSI based updates, restart scanning if needed.
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v4 2/8] dt-bindings: net: wireless: qcom,ath10k: Document NVMEM cells
From: Krzysztof Kozlowski @ 2026-06-12 8:26 UTC (permalink / raw)
To: Loic Poulain, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Jens Axboe,
Johannes Berg, Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Bartosz Golaszewski
In-Reply-To: <20260609-block-as-nvmem-v4-2-45712e6b22c6@oss.qualcomm.com>
On 09/06/2026 09:52, Loic Poulain wrote:
> Document the NVMEM cells supported by the ath10k driver, the
> mac-address, pre-calibration data, and calibration data.
>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> ---
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v4 2/8] dt-bindings: net: wireless: qcom,ath10k: Document NVMEM cells
From: Loic Poulain @ 2026-06-12 7:57 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, linux-mmc, devicetree,
linux-kernel, linux-arm-msm, linux-block, linux-wireless, ath10k,
linux-bluetooth, netdev, daniel, Bartosz Golaszewski
In-Reply-To: <20260610-funny-paper-warthog-25fa0a@quoll>
On Wed, Jun 10, 2026 at 9:16 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Tue, Jun 09, 2026 at 09:52:27AM +0200, Loic Poulain wrote:
> > Document the NVMEM cells supported by the ath10k driver, the
> > mac-address, pre-calibration data, and calibration data.
> >
> > Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> > Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> > ---
> > .../devicetree/bindings/net/wireless/qcom,ath10k.yaml | 16 ++++++++++++++++
> > 1 file changed, 16 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
> > index c21d66c7cd558ab792524be9afec8b79272d1c87..7391df5e7071e626af4c64b9919d48c41ac09f1e 100644
> > --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
> > +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
> > @@ -92,6 +92,22 @@ properties:
> >
> > ieee80211-freq-limit: true
> >
> > + nvmem-cells:
> > + minItems: 1
> > + maxItems: 3
> > + description: |
>
> If there is going to be resend:
> Do not need '|' unless you need to preserve formatting.
Sure, thanks.
>
> > + References to nvmem cells for MAC address and/or calibration data.
> > + Supported cell names are mac-address, calibration, and pre-calibration.
> > +
> > + nvmem-cell-names:
> > + minItems: 1
> > + maxItems: 3
> > + items:
> > + enum:
> > + - mac-address
> > + - calibration
> > + - pre-calibration
>
> This means you expect random order with variable number of items. Is
> that intentional? If yes, please provide short explanation in the commit
> msg.
Yes we may or may have any of those cells. Will document.
Thanks,
Loic
^ permalink raw reply
* [PATCH 18/20] wifi: mt76: mt7925: align scan IE and EFUSE TLV lengths to 4 bytes for MT7928
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, Xiong
In-Reply-To: <20260612075339.2578327-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
MT7928 firmware requires 4-byte aligned TLV payloads. Round up
UNI_SCAN_IE allocation with ALIGN(..., 4) and track padded length.
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index ffe687afcf6e..e8edc8c1acca 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1582,7 +1582,8 @@ int mt7925_mcu_set_eeprom(struct mt792x_dev *dev)
.tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
.len = cpu_to_le16(sizeof(req) - 4),
.buffer_mode = EE_MODE_EFUSE,
- .format = EE_FORMAT_WHOLE
+ .format = EE_FORMAT_WHOLE,
+ .buf_len = 0
};
return mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(EFUSE_CTRL),
@@ -3036,11 +3037,11 @@ mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
struct ieee80211_scan_ies *scan_ies)
{
u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN;
+ u32 ies_len, alloc_len;
struct scan_ie_tlv *ie;
enum nl80211_band i;
struct tlv *tlv;
const u8 *ies;
- u16 ies_len;
for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
if (i == NL80211_BAND_60GHZ)
@@ -3052,11 +3053,16 @@ mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
if (!ies || !ies_len)
continue;
- if (ies_len > max_len)
+ if (is_mt7928(mdev))
+ alloc_len = ALIGN(sizeof(*ie) + ies_len, 4);
+ else
+ alloc_len = sizeof(*ie) + ies_len;
+
+ if (alloc_len > max_len)
return;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE,
- sizeof(*ie) + ies_len);
+ alloc_len);
ie = (struct scan_ie_tlv *)tlv;
memcpy(ie->ies, ies, ies_len);
@@ -3074,7 +3080,7 @@ mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
break;
}
- max_len -= (sizeof(*ie) + ies_len);
+ max_len -= alloc_len;
}
}
--
2.45.2
^ permalink raw reply related
* [PATCH 20/20] wifi: mt76: mt7925: add MT7928 PCIe support
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075339.2578327-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Register MT7928 (0x7928, 0x7935) in the PCI device table and
declare MODULE_FIRMWARE for all four MT7928 firmware blobs.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 1ad5847d4a8c..1514494f6c7b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -22,6 +22,10 @@ static const struct pci_device_id mt7925_pci_device_table[] = {
.driver_data = (kernel_ulong_t)MT7927_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0738),
.driver_data = (kernel_ulong_t)MT7927_FIRMWARE_WM },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7928),
+ .driver_data = (kernel_ulong_t)MT7928_FIRMWARE_WM },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7935),
+ .driver_data = (kernel_ulong_t)MT7928_FIRMWARE_WM },
{ },
};
@@ -663,6 +667,11 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
"MT7927 raw CHIPID=0x%04x, forcing chip=0x7927\n",
mt76_chip(mdev));
mdev->rev = (0x7927 << 16) | (mdev->rev & 0xff);
+ } else if (is_mt7928_hw && mt76_chip(mdev) != 0x7928) {
+ dev_info(mdev->dev,
+ "MT7928 raw CHIPID=0x%04x, forcing chip=0x7928\n",
+ mt76_chip(mdev));
+ mdev->rev = (0x7928 << 16) | (mdev->rev & 0xff);
}
mt76_rmw_field(dev, MT_HW_EMI_CTL, MT_HW_EMI_CTL_SLPPROT_EN, 1);
@@ -913,6 +922,10 @@ MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
MODULE_FIRMWARE(MT7925_ROM_PATCH);
MODULE_FIRMWARE(MT7927_FIRMWARE_WM);
MODULE_FIRMWARE(MT7927_ROM_PATCH);
+MODULE_FIRMWARE(MT7928_FIRMWARE_WM);
+MODULE_FIRMWARE(MT7928_ROM_PATCH);
+MODULE_FIRMWARE(MT7928_CB_ROM_PATCH);
+MODULE_FIRMWARE(MT7928_PHY_RAM);
MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_DESCRIPTION("MediaTek MT7925E (PCIe) wireless driver");
--
2.45.2
^ permalink raw reply related
* [PATCH 19/20] wifi: mt76: mt7925: add MT7928 per-chip PCIe register definitions
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, Xiong
In-Reply-To: <20260612075339.2578327-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
MT7928 maps PCIe MAC registers through base 0x74040000. Add
MT7928_PCIE_MAC_{INT_ENABLE,PM} macros and override dev->pcie_reg
at probe time for MT7928 hardware.
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 6 ++++++
drivers/net/wireless/mediatek/mt76/mt7925/regs.h | 5 +++++
2 files changed, 11 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 719f53ddf1eb..1ad5847d4a8c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -473,6 +473,11 @@ static const struct mt792x_pcie_reg mt7925_pcie_reg = {
.pm = MT7925_PCIE_MAC_PM,
};
+static const struct mt792x_pcie_reg mt7928_pcie_reg = {
+ .imask = MT7928_PCIE_MAC_INT_ENABLE,
+ .pm = MT7928_PCIE_MAC_PM,
+};
+
static const struct mt792x_irq_map mt7925_irq_map = {
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
.tx = {
@@ -609,6 +614,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
dev->pcie_reg = &mt7925_pcie_reg;
if (is_mt7928_hw) {
+ dev->pcie_reg = &mt7928_pcie_reg;
dev->irq_map = &mt7928_irq_map;
mdev->rev = 0x7928 << 16;
} else if (is_mt7927_hw) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index af6291fc53cd..cb937d565a80 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -114,6 +114,11 @@
#define MT7925_PCIE_MAC_INT_ENABLE MT7925_PCIE_MAC(0x188)
#define MT7925_PCIE_MAC_PM MT7925_PCIE_MAC(0x194)
+#define MT7928_PCIE_MAC_BASE 0x74040000
+#define MT7928_PCIE_MAC(ofs) (MT7928_PCIE_MAC_BASE + (ofs))
+#define MT7928_PCIE_MAC_INT_ENABLE MT7928_PCIE_MAC(0x188)
+#define MT7928_PCIE_MAC_PM MT7928_PCIE_MAC(0x194)
+
#define MT_DMASHDL_LITE_BASE 0x20026200
#define MT_DMASHDL_LITE(ofs) (MT_DMASHDL_LITE_BASE + (ofs))
#define MT_DMASHDL_LITE_MAIN_CONTROL MT_DMASHDL_LITE(0x004)
--
2.45.2
^ permalink raw reply related
* [PATCH 16/20] wifi: mt76: mt7925: add MT7928 TXD/TXS/TX_DONE support
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, Xiong
From: Emery Hsin <emery.hsin@mediatek.com>
Add MT7928 TXD v2 fields, per-chip WTBL register addresses, UNI
TxDone event parsing, and TXS format acceptance for MPDU/PPDU.
Suppress HW AMSDU on management frames for MT7928.
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt76_connac.h | 1 +
.../wireless/mediatek/mt76/mt76_connac3_mac.h | 42 ++++
.../net/wireless/mediatek/mt76/mt7925/mac.c | 219 +++++++++++++++++-
.../net/wireless/mediatek/mt76/mt7925/mac.h | 9 +-
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 25 ++
.../wireless/mediatek/mt76/mt7925/mt7925.h | 1 +
.../net/wireless/mediatek/mt76/mt7925/regs.h | 6 +
7 files changed, 291 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index e21c393bb26d..f99a512145c5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -300,6 +300,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
case 0x7902:
case 0x7925:
case 0x7927:
+ case 0x7928:
case 0x7663:
case 0x7622:
return false;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
index 247e2e7a47d8..d2d63767bfd0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
@@ -18,6 +18,11 @@ enum {
MT_LMAC_PSMP0,
};
+enum {
+ TXS_FM_MPDU = 0,
+ TXS_FM_PPDU = 2,
+};
+
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
@@ -236,7 +241,9 @@ enum tx_frag_idx {
#define MT_TXD2_HDR_PAD GENMASK(11, 10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_OWN_MAC_MAP BIT(8)
+#define MT_TXD2_OWN_MAC_MAP_V2 BIT(9)
#define MT_TXD2_BF_TYPE GENMASK(6, 7)
+#define MT_TXD2_BF_TYPE_V2 GENMASK(6, 8)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
@@ -261,6 +268,7 @@ enum tx_frag_idx {
#define MT_TXD5_BYPASS_TBB BIT(14)
#define MT_TXD5_BYPASS_RBB BIT(13)
#define MT_TXD5_BSS_COLOR_ZERO BIT(12)
+#define MT_TXD5_OCUP_BY_OTHER_LNK BIT(11)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
@@ -270,15 +278,19 @@ enum tx_frag_idx {
#define MT_TXD6_VTA BIT(28)
#define MT_TXD6_FIXED_BW BIT(25)
#define MT_TXD6_BW GENMASK(24, 22)
+#define MT_TXD6_BW_V2 GENMASK(25, 22)
#define MT_TXD6_TX_RATE GENMASK(21, 16)
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
+#define MT_TXD6_TIMESTAMP_OFS_EN_V2 GENMASK(15, 13)
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
+#define MT_TXD6_TIMESTAMP_OFS_IDX_V2 GENMASK(12, 8)
#define MT_TXD6_TID_ADDBA GENMASK(10, 8)
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
#define MT_TXD6_MSDU_CNT_V2 GENMASK(15, 10)
#define MT_TXD6_DIS_MAT BIT(3)
#define MT_TXD6_DAS BIT(2)
#define MT_TXD6_AMSDU_CAP BIT(1)
+#define MT_TXD6_MLD BIT(0)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_IP_SUM BIT(29)
@@ -287,6 +299,9 @@ enum tx_frag_idx {
#define MT_TXD7_CTXD BIT(26)
#define MT_TXD7_CTXD_CNT GENMASK(25, 22)
#define MT_TXD7_UDP_TCP_SUM BIT(15)
+#define MT_TXD7_IMMEDIATE_TX BIT(14)
+#define MT_TXD7_FORCE_RTS_CTS BIT(13)
+#define MT_TXD7_ENABLE_ICI BIT(12)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TXD9_WLAN_IDX GENMASK(23, 8)
@@ -397,4 +412,31 @@ enum tx_frag_idx {
#define MT_TXS7_MPDU_RETRY_BYTE_SCALE BIT(15)
#define MT_TXS7_MPDU_RETRY_BYTE GENMASK(14, 0)
+struct mt7928_uni_txdone_event {
+ __le16 tag;
+ __le16 len;
+
+ u8 pid; /* HW packet ID */
+ u8 status; /* TX_RESULT_xx */
+ __le16 seq; /* packet sequence number */
+
+ u8 wcid; /* WLAN index (WTBL) */
+ u8 tx_count; /* TX attempts including retries */
+ __le16 tx_rate;
+
+ u8 flag; /* TXS_WITH_ADVANCED_INFO or TXS_IS_EXIST */
+ u8 tid;
+ u8 rsp_rate;
+ u8 rate_tbl_idx; /* last TX rate index from WLAN table */
+
+ u8 bw; /* bandwidth used for this PPDU */
+ u8 tx_pwr; /* dBm */
+ u8 flush_reason;
+ u8 rsv[1];
+
+ __le32 tx_delay; /* unit: 32us, UMAC TX to TX status */
+ __le32 timestamp; /* local TSF at first bit of MAC header */
+ __le32 applied_flags;
+} __packed;
+
#endif /* __MT76_CONNAC3_MAC_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 44d5a1e7e415..b7038bfa12c3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -12,10 +12,17 @@
bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask)
{
- mt76_rmw(dev, MT7925_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
+ u32 wtbl_update;
+
+ if (is_mt7928(&dev->mt76))
+ wtbl_update = MT7928_WTBL_UPDATE;
+ else
+ wtbl_update = MT7925_WTBL_UPDATE;
+
+ mt76_rmw(dev, wtbl_update, MT_WTBL_UPDATE_WLAN_IDX,
FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
- return mt76_poll(dev, MT7925_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY,
+ return mt76_poll(dev, wtbl_update, MT_WTBL_UPDATE_BUSY,
0, 5000);
}
@@ -159,10 +166,17 @@ void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev,
{
u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
- mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
- /* use wtbl spe idx */
- mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
- mt76_wr(dev, MT_WTBL_ITCR, ctrl);
+ if (is_mt7928(&dev->mt76)) {
+ mt76_wr(dev, MT7928_WTBL_ITDR0, rate_idx);
+ /* use wtbl spe idx */
+ mt76_wr(dev, MT7928_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
+ mt76_wr(dev, MT7928_WTBL_ITCR, ctrl);
+ } else {
+ mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
+ /* use wtbl spe idx */
+ mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
+ mt76_wr(dev, MT_WTBL_ITCR, ctrl);
+ }
}
/* The HW does not translate the mac header to 802.3 for mesh point */
@@ -705,6 +719,9 @@ mt7925_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
txwi[2] |= cpu_to_le32(val);
+ if (is_mt7928(dev) && ieee80211_is_mgmt(hdr->frame_control))
+ txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
+
txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
if (ieee80211_is_beacon(fc))
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
@@ -808,7 +825,11 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
txwi[5] = cpu_to_le32(val);
- val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
+ if (is_mt7928(dev))
+ val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT_V2, 1);
+ else
+ val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
+
if (vif && (!ieee80211_vif_is_mld(vif) ||
(q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)))
val |= MT_TXD6_DIS_MAT;
@@ -836,6 +857,10 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
}
txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
+
+ if (is_mt7928(dev))
+ txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_BW_V2, 8));
+
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
}
@@ -916,7 +941,6 @@ mt7925_mac_add_txs_skb(struct mt792x_dev *dev, struct mt76_wcid *wcid,
goto out_no_skb;
txs = le32_to_cpu(txs_data[0]);
-
info = IEEE80211_SKB_CB(skb);
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
@@ -1033,15 +1057,188 @@ mt7925_mac_add_txs_skb(struct mt792x_dev *dev, struct mt76_wcid *wcid,
return !!skb;
}
-void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
+static bool
+mt7928_mac_add_txs_skb_msg(struct mt792x_dev *dev, struct mt76_wcid *wcid,
+ int pid, struct mt7928_uni_txdone_event *pevt)
{
+ struct mt76_sta_stats *stats = &wcid->stats;
+ struct ieee80211_supported_band *sband;
+ struct mt76_dev *mdev = &dev->mt76;
+ struct ieee80211_tx_info *info;
+ struct sk_buff_head list;
+ u32 txrate, mode, stbc;
+ struct rate_info rate;
+ struct mt76_phy *mphy;
+ struct sk_buff *skb;
+ bool cck = false;
+
+ mt76_tx_status_lock(mdev, &list);
+ skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
+ if (!skb)
+ goto out_no_skb;
+
+ info = IEEE80211_SKB_CB(skb);
+ if (!pevt->status)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ info->status.ampdu_len = 1;
+ info->status.ampdu_ack_len = !!(info->flags &
+ IEEE80211_TX_STAT_ACK);
+
+ info->status.rates[0].idx = -1;
+
+ txrate = pevt->tx_rate;
+
+ rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
+ rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
+ stbc = FIELD_GET(MT_TX_RATE_STBC, txrate);
+
+ if (stbc && rate.nss > 1)
+ rate.nss >>= 1;
+
+ if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
+ stats->tx_nss[rate.nss - 1]++;
+ if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
+ stats->tx_mcs[rate.mcs]++;
+
+ mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
+ switch (mode) {
+ case MT_PHY_TYPE_CCK:
+ cck = true;
+ fallthrough;
+ case MT_PHY_TYPE_OFDM:
+ mphy = mt76_dev_phy(mdev, wcid->phy_idx);
+
+ if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
+ sband = &mphy->sband_5g.sband;
+ else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
+ sband = &mphy->sband_6g.sband;
+ else
+ sband = &mphy->sband_2g.sband;
+
+ rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
+ rate.legacy = sband->bitrates[rate.mcs].bitrate;
+ break;
+ case MT_PHY_TYPE_HT:
+ case MT_PHY_TYPE_HT_GF:
+ if (rate.mcs > 31)
+ goto out;
+
+ rate.flags = RATE_INFO_FLAGS_MCS;
+ if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
+ rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case MT_PHY_TYPE_VHT:
+ if (rate.mcs > 9)
+ goto out;
+
+ rate.flags = RATE_INFO_FLAGS_VHT_MCS;
+ break;
+ case MT_PHY_TYPE_HE_SU:
+ case MT_PHY_TYPE_HE_EXT_SU:
+ case MT_PHY_TYPE_HE_TB:
+ case MT_PHY_TYPE_HE_MU:
+ if (rate.mcs > 11)
+ goto out;
+
+ rate.he_gi = wcid->rate.he_gi;
+ rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
+ rate.flags = RATE_INFO_FLAGS_HE_MCS;
+ break;
+ case MT_PHY_TYPE_EHT_SU:
+ case MT_PHY_TYPE_EHT_TRIG:
+ case MT_PHY_TYPE_EHT_MU:
+ if (rate.mcs > 13)
+ goto out;
+
+ rate.eht_gi = wcid->rate.eht_gi;
+ rate.flags = RATE_INFO_FLAGS_EHT_MCS;
+ break;
+ default:
+ goto out;
+ }
+
+ stats->tx_mode[mode]++;
+
+ switch (pevt->bw) {
+ case IEEE80211_STA_RX_BW_160:
+ rate.bw = RATE_INFO_BW_160;
+ stats->tx_bw[3]++;
+ break;
+ case IEEE80211_STA_RX_BW_80:
+ rate.bw = RATE_INFO_BW_80;
+ stats->tx_bw[2]++;
+ break;
+ case IEEE80211_STA_RX_BW_40:
+ rate.bw = RATE_INFO_BW_40;
+ stats->tx_bw[1]++;
+ break;
+ default:
+ rate.bw = RATE_INFO_BW_20;
+ stats->tx_bw[0]++;
+ break;
+ }
+ wcid->rate = rate;
+
+out:
+ mt76_tx_status_skb_done(mdev, skb, &list);
+
+out_no_skb:
+ mt76_tx_status_unlock(mdev, &list);
+
+ return !!skb;
+}
+
+void mt7928_mac_add_txs_msg(struct mt792x_dev *dev,
+ void *evt)
+{
+ struct mt7928_uni_txdone_event *done_evt;
struct mt792x_link_sta *mlink = NULL;
struct mt76_wcid *wcid;
- __le32 *txs_data = data;
u16 wcidx;
u8 pid;
- if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
+ done_evt = (struct mt7928_uni_txdone_event *)evt;
+ wcidx = done_evt->wcid;
+ pid = done_evt->pid;
+
+ if (pid < MT_PACKET_ID_FIRST)
+ return;
+
+ if (wcidx >= MT792x_WTBL_SIZE)
+ return;
+
+ rcu_read_lock();
+
+ wcid = mt76_wcid_ptr(dev, wcidx);
+ if (!wcid)
+ goto out;
+
+ mlink = container_of(wcid, struct mt792x_link_sta, wcid);
+
+ mt7928_mac_add_txs_skb_msg(dev, wcid, pid, done_evt);
+ if (!wcid->sta)
+ goto out;
+
+ mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
+
+out:
+ rcu_read_unlock();
+}
+
+void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
+{
+ struct mt792x_link_sta *mlink = NULL;
+ __le32 *txs_data = data;
+ struct mt76_wcid *wcid;
+ u8 pid, txs_fm;
+ u16 wcidx;
+
+ txs_fm = le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT);
+
+ if (is_mt7928(&dev->mt76) && txs_fm != TXS_FM_MPDU && txs_fm != TXS_FM_PPDU)
+ return;
+ else if (txs_fm > 1)
return;
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.h b/drivers/net/wireless/mediatek/mt76/mt7925/mac.h
index 67148c87de76..567d072cba02 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.h
@@ -14,7 +14,14 @@
static inline u32 mt7925_mac_wtbl_lmac_addr(struct mt792x_dev *dev, u16 wcid, u8 dw)
{
- mt76_wr(dev, MT7925_WTBLON_TOP_WDUCR,
+ u32 wdu_cr;
+
+ if (is_mt7928(&dev->mt76))
+ wdu_cr = MT7928_WTBLON_TOP_WDUCR;
+ else
+ wdu_cr = MT7925_WTBLON_TOP_WDUCR;
+
+ mt76_wr(dev, wdu_cr,
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
return MT_WTBL_LMAC_OFFS(wcid, dw);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 0b4ca5cf5734..ffe687afcf6e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -446,6 +446,31 @@ mt7925_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)
while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) {
switch (le16_to_cpu(tlv->tag)) {
+ case UNI_EVENT_TX_DONE_MSG:
+ struct mt7928_uni_txdone_event *evt;
+
+ if (!is_mt7928(&dev->mt76))
+ break;
+
+ evt = (struct mt7928_uni_txdone_event *)tlv;
+ if (evt->status) {
+ dev_info(dev->mt76.dev,
+ "TxDone: pid=%u status=%#x sn=%#x wcid=%u "
+ "cnt=%u rate=%#x flag=%#x tid=%u pwr=%u "
+ "rsp_rate=%#x rate_idx=%u bw=%u flush=%#x "
+ "delay=%#x ts=%#x flags=%#x\n",
+ evt->pid, evt->status,
+ le16_to_cpu(evt->seq), evt->wcid,
+ evt->tx_count, le16_to_cpu(evt->tx_rate),
+ evt->flag, evt->tid, evt->tx_pwr,
+ evt->rsp_rate, evt->rate_tbl_idx,
+ evt->bw, evt->flush_reason,
+ le32_to_cpu(evt->tx_delay),
+ le32_to_cpu(evt->timestamp),
+ le32_to_cpu(evt->applied_flags));
+ }
+ mt7928_mac_add_txs_msg(dev, evt);
+ break;
case UNI_EVENT_TX_DONE_RAW:
txs = (struct mt7925_mcu_txs_event *)tlv->data;
mt7925_mac_add_txs(dev, txs->data);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index a5414fa2736f..321e732347f2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -354,6 +354,7 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
int mt7925e_mac_reset(struct mt792x_dev *dev);
int mt7925e_mcu_init(struct mt792x_dev *dev);
void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);
+void mt7928_mac_add_txs_msg(struct mt792x_dev *dev, void *evt);
void mt7925_set_runtime_pm(struct mt792x_dev *dev);
void mt7925_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index 253ba72310ec..af6291fc53cd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -97,12 +97,18 @@
#define MT_WFSYS_SW_RST_B 0x7c000140
#define MT7925_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370)
+#define MT7928_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x400)
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0)
#define MT7925_WTBL_UPDATE MT_WTBLON_TOP(0x380)
+#define MT7928_WTBL_UPDATE MT_WTBLON_TOP(0x410)
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
+#define MT7928_WTBL_ITCR MT_WTBLON_TOP(0x440)
+#define MT7928_WTBL_ITDR0 MT_WTBLON_TOP(0x448)
+#define MT7928_WTBL_ITDR1 MT_WTBLON_TOP(0x44c)
+
#define MT7925_PCIE_MAC_BASE 0x10000
#define MT7925_PCIE_MAC(ofs) (MT7925_PCIE_MAC_BASE + (ofs))
#define MT7925_PCIE_MAC_INT_ENABLE MT7925_PCIE_MAC(0x188)
--
2.45.2
^ permalink raw reply related
* [PATCH 17/20] wifi: mt76: mt7925: add MMIO register remapping table for MT7928
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, Leon Yen
In-Reply-To: <20260612075339.2578327-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
MT7928 has a different physical address layout. Add a dedicated
mt7928_fixed_map[] remapping table and select it at runtime. Set
mdev->rev early in probe for correct chip revision detection.
Signed-off-by: Leon Yen <leon.yen@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/pci.c | 109 +++++++++++++++++-
1 file changed, 103 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index f79d4143e38b..719f53ddf1eb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -110,7 +110,7 @@ static u32 mt7925_reg_map_l2(struct mt792x_dev *dev, u32 addr)
static u32 __mt7925_reg_addr(struct mt792x_dev *dev, u32 addr)
{
- static const struct mt76_connac_reg_map fixed_map[] = {
+ static const struct mt76_connac_reg_map default_fixed_map[] = {
{ 0x830c0000, 0x000000, 0x0001000 }, /* WF_MCU_BUS_CR_REMAP */
{ 0x54000000, 0x002000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA0 */
{ 0x55000000, 0x003000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA1 */
@@ -164,14 +164,109 @@ static u32 __mt7925_reg_addr(struct mt792x_dev *dev, u32 addr)
{ 0x7c500000, 0x060000, 0x200000 }, /* remap */
{ 0x0, 0x0, 0x0 } /* End */
};
- int i;
+ /* The remap table was ordered from highest to lowest frequency
+ * to improve lookup efficiency.
+ */
+ static const struct mt76_connac_reg_map mt7928_fixed_map[] = {
+ {0x54000000, 0x002000, 0x01000}, /* WFDMA_0 (PCIE0 MCU DMA0) */
+ {0x55000000, 0x003000, 0x01000}, /* WFDMA_1 (PCIE0 MCU DMA1) */
+ {0x57000000, 0x005000, 0x01000}, /* WFDMA_3 (MCU wrap CR) */
+ {0x58000000, 0x006000, 0x01000}, /* WFDMA_4 (PCIE1 MCU DMA0) */
+ {0x59000000, 0x007000, 0x01000}, /* WFDMA_5 (PCIE1 MCU DMA1) */
+ {0x56000000, 0x004000, 0x01000}, /* WFDMA_2 (Reserved) */
+ {0x820D0000, 0x030000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */
+ {0x820C4000, 0x0A8000, 0x04000}, /* WF_LMAC_TOP (WF_UWTBL) */
+ {0x820C0000, 0x008000, 0x04000}, /* WF_UMAC_TOP (PLE) */
+ {0x820C8000, 0x00C000, 0x02000}, /* WF_UMAC_TOP (PSE) */
+ {0x820CC000, 0x00E000, 0x02000}, /* WF_UMAC_TOP (PP) */
+ {0x820F0000, 0x0A0000, 0x00400}, /* WF_LMAC_TOP (WF_CFG) */
+ {0x820F1000, 0x0A0600, 0x00200}, /* WF_LMAC_TOP (WF_TRB) */
+ {0x820F2000, 0x0A0800, 0x00400}, /* WF_LMAC_TOP (WF_AGG) */
+ {0x820F3000, 0x0A0C00, 0x00400}, /* WF_LMAC_TOP (WF_ARB) */
+ {0x820F4000, 0x0A1000, 0x00400}, /* WF_LMAC_TOP (WF_TMAC) */
+ {0x820F5000, 0x0A1400, 0x00800}, /* WF_LMAC_TOP (WF_RMAC) */
+ {0x820F7000, 0x0A1E00, 0x00200}, /* WF_LMAC_TOP (WF_DMA) */
+ {0x820F9000, 0x0A3400, 0x00200}, /* WF_LMAC_TOP (WF_WTBLOFF) */
+ {0x820FA000, 0x0A4000, 0x00200}, /* WF_LMAC_TOP (WF_ETBF) */
+ {0x820FB000, 0x0A4200, 0x00400}, /* WF_LMAC_TOP (WF_LPON) */
+ {0x820FC000, 0x0A4600, 0x00200}, /* WF_LMAC_TOP (WF_INT) */
+ {0x820FD000, 0x0A4800, 0x00800}, /* WF_LMAC_TOP (WF_MIB) */
+ {0x820E0000, 0x020000, 0x00400}, /* WF_LMAC_TOP (WF_CFG) */
+ {0x820E1000, 0x020400, 0x00200}, /* WF_LMAC_TOP (WF_TRB) */
+ {0x820E2000, 0x020800, 0x00400}, /* WF_LMAC_TOP (WF_AGG) */
+ {0x820E3000, 0x020C00, 0x00400}, /* WF_LMAC_TOP (WF_ARB) */
+ {0x820E4000, 0x021000, 0x00400}, /* WF_LMAC_TOP (WF_TMAC) */
+ {0x820E5000, 0x021400, 0x00800}, /* WF_LMAC_TOP (WF_RMAC) */
+ {0x820CE000, 0x021C00, 0x00200}, /* WF_LMAC_TOP (WF_SEC) */
+ {0x820E7000, 0x021E00, 0x00200}, /* WF_LMAC_TOP (WF_DMA) */
+ {0x820CF000, 0x022000, 0x01000}, /* WF_LMAC_TOP (WF_PF) */
+ {0x820E9000, 0x023400, 0x00200}, /* WF_LMAC_TOP (WF_WTBLOFF) */
+ {0x820EA000, 0x024000, 0x00200}, /* WF_LMAC_TOP (WF_ETBF) */
+ {0x820EB000, 0x024200, 0x00400}, /* WF_LMAC_TOP (WF_LPON) */
+ {0x820EC000, 0x024600, 0x00200}, /* WF_LMAC_TOP (WF_INT) */
+ {0x820ED000, 0x024800, 0x00800}, /* WF_LMAC_TOP (WF_MIB) */
+ {0x820CA000, 0x026000, 0x02000}, /* WF_LMAC_TOP (WF_MUCOP) */
+ {0x7C500000, 0x060000, 0x200000}, /* remap */
+ {0x7C000000, 0x0F0000, 0x10000}, /* CONN_INFRA (off2on) */
+ {0x7C060000, 0x0E0000, 0x10000}, /* remap MT_CONN_ON_LPCTL and MT_CONN_ON_MISC */
+ {0x20060000, 0x0E0000, 0x10000}, /* CONN_INFRA conn_host_csr_top */
+ {0x7C010000, 0x100000, 0x10000}, /* CONN_INFRA (gpio clkgen cfg) */
+ {0x7C050000, 0x1A0000, 0x10000}, /* CONN_INFRA SYSRAM */
+ {0x7C080000, 0x190000, 0x10000}, /* CONN_INFRA (coex, pta) */
+ {0x7C070000, 0x180000, 0x10000}, /* CONN_INFRA Semaphore */
+ {0x7C040000, 0x170000, 0x10000}, /* CONN_INFRA (bus, afe) */
+ {0x7C026000, 0x0D6000, 0x0019C}, /* remap DMASHL TOP */
+ {0x20020000, 0x0D0000, 0x0C000}, /* CONN_INFRA wf_dma_host_side_cr */
+ {0x200B0000, 0x050000, 0x10000}, /* CONN_INFRA conn_von_sysram */
+ {0x20090000, 0x150000, 0x08000}, /* CONN_INFRA von_connsys_s0-s7 */
+ {0x7C098000, 0x158000, 0x08000}, /* CONN_INFRA von_connsys_hclk_s0-s7 */
+ {0x20030000, 0x160000, 0x10000}, /* CONN_INFRA CCIF */
+ {0x70000000, 0x1E0000, 0x10000}, /* CONN_INFRA CONN2AP */
+ {0x830C0000, 0x000000, 0x01000}, /* WF_MCU_BUS_CR_REMAP */
+ {0x81020000, 0x0C0000, 0x10000}, /* WF_TOP_MISC_ON */
+ {0x80020000, 0x0B0000, 0x10000}, /* WF_TOP_MISC_OFF */
+ {0x81040000, 0x120000, 0x01000}, /* WF_MCU_CFG_ON */
+ {0x00400000, 0x080000, 0x10000}, /* WF_MCU_SYSRAM */
+ {0x00410000, 0x090000, 0x10000}, /* WF_MCU_SYSRAM (Common driver) */
+ {0x88000000, 0x140000, 0x10000}, /* WF_MCU_CFG_LS */
+ {0x80010000, 0x124000, 0x01000}, /* WF_AXIDMA */
+ {0x81050000, 0x121000, 0x01000}, /* WF_MCU_EINT */
+ {0x81060000, 0x122000, 0x01000}, /* WF_MCU_GPT */
+ {0x81070000, 0x123000, 0x01000}, /* WF_MCU_WDT */
+ {0x830A0000, 0x040000, 0x10000}, /* WF_PHY_MAP0 */
+ {0x83090000, 0x060000, 0x10000}, /* WF_PHY_MAP2 */
+ {0x83000000, 0x110000, 0x10000}, /* WF_PHY_MAP3 */
+ {0x83010000, 0x130000, 0x10000}, /* WF_PHY_MAP4 */
+ {0x81030000, 0x0AE000, 0x00100}, /* WFSYS_AON */
+ {0x81031000, 0x0AE100, 0x00100}, /* WFSYS_AON */
+ {0x81032000, 0x0AE200, 0x00100}, /* WFSYS_AON */
+ {0x81033000, 0x0AE300, 0x00100}, /* WFSYS_AON */
+ {0x81034000, 0x0AE400, 0x00100}, /* WFSYS_AON */
+ {0xE0400000, 0x070000, 0x10000}, /* WF_UMCA_SYSRAM */
+ {0x70010000, 0x1C0000, 0x10000}, /* CB Infra1 */
+ {0x70020000, 0x1F0000, 0x10000}, /* Reserved for CBTOP, can't switch */
+ {0x74040000, 0x1D0000, 0x10000}, /* CB PCIe (cbtop remap) */
+ {0x18010000, 0x100000, 0x10000}, /* remap MT_HW_EMI_CTRL */
+ {0x00000000, 0x000000, 0x00000}, /* END */
+ };
+ const struct mt76_connac_reg_map *fixed_map;
+ size_t array_size;
+ u32 i;
if (addr < 0x200000)
return addr;
mt7925_reg_remap_restore(dev);
- for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
+ if (is_mt7928(&dev->mt76)) {
+ fixed_map = mt7928_fixed_map;
+ array_size = ARRAY_SIZE(mt7928_fixed_map);
+ } else {
+ fixed_map = default_fixed_map;
+ array_size = ARRAY_SIZE(default_fixed_map);
+ }
+
+ for (i = 0; i < array_size; i++) {
u32 ofs;
if (addr < fixed_map[i].phys)
@@ -513,12 +608,14 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
dev->hif_ops = &mt7925_pcie_ops;
dev->pcie_reg = &mt7925_pcie_reg;
- if (is_mt7928_hw)
+ if (is_mt7928_hw) {
dev->irq_map = &mt7928_irq_map;
- else if (is_mt7927_hw)
+ mdev->rev = 0x7928 << 16;
+ } else if (is_mt7927_hw) {
dev->irq_map = &mt7927_irq_map;
- else
+ } else {
dev->irq_map = &mt7925_irq_map;
+ }
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
--
2.45.2
^ permalink raw reply related
* [PATCH 15/20] wifi: mt76: mt7925: add MT7928 DMA configuration
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, FC Wei,
Xiong
In-Reply-To: <20260612075313.2578154-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Add MT7928 DMA queue layout, DMASHDL configuration, prefetch ring
setup, and WFDMA interrupt priority initialization. Select the
MT7928-specific layout and GLO_CFG path in mt7925_dma_init().
Signed-off-by: FC Wei <fc.wei@mediatek.com>
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/mcu.h | 21 +++++
.../wireless/mediatek/mt76/mt7925/mt7925.h | 8 ++
.../net/wireless/mediatek/mt76/mt7925/pci.c | 91 ++++++++++++++++--
.../net/wireless/mediatek/mt76/mt7925/regs.h | 21 +++++
.../net/wireless/mediatek/mt76/mt792x_dma.c | 94 ++++++++++++++++---
.../net/wireless/mediatek/mt76/mt792x_regs.h | 19 +++-
6 files changed, 233 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
index 293f173b23dd..1613c4765186 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
@@ -175,6 +175,27 @@ enum connac3_mcu_cipher_type {
CONNAC3_CIPHER_GCMP_256 = 12,
};
+enum DMASHDL_GROUP_IDX {
+ DMASHDL_GROUP_0 = 0,
+ DMASHDL_GROUP_1,
+ DMASHDL_GROUP_2,
+ DMASHDL_GROUP_3,
+ DMASHDL_GROUP_4,
+ DMASHDL_GROUP_5,
+ DMASHDL_GROUP_6,
+ DMASHDL_GROUP_7,
+ DMASHDL_GROUP_8,
+ DMASHDL_GROUP_9,
+ DMASHDL_GROUP_10,
+ DMASHDL_GROUP_11,
+ DMASHDL_GROUP_12,
+ DMASHDL_GROUP_13,
+ DMASHDL_GROUP_14,
+ DMASHDL_GROUP_15,
+ DMASHDL_GROUP_NUM,
+ DMASHDL_LITE_GROUP_NUM = 64
+};
+
struct mt7925_mcu_scan_chinfo_event {
u8 nr_chan;
u8 alpha2[3];
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index 4cc259418afc..a5414fa2736f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -15,6 +15,7 @@
#define MT7925_RX_RING_SIZE 1536
#define MT7925_RX_MCU_RING_SIZE 512
+#define MT7928_RX_MCU_WA_RING_SIZE 512
#define MT7925_EEPROM_SIZE 3584
#define MT7925_TOKEN_SIZE 8192
@@ -139,6 +140,13 @@ enum mt7927_rxq_id {
MT7927_RXQ_DATA2 = 7,
};
+enum mt7928_rxq_id {
+ MT7928_RXQ_BAND0,
+ MT7928_RXQ_BAND1 = 2,
+ MT7928_RXQ_MCU_WM = 3,
+ MT7928_RXQ_MCU_WM2 = 1, /* for tx done */
+};
+
enum {
MODE_OPEN = 0,
MODE_SHARED = 1,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 6a65c630f85a..f79d4143e38b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -252,6 +252,27 @@ static const struct mt792x_dma_layout mt7927_dma_layout = {
MT_RX_DATA_RING_BASE),
};
+static const struct mt792x_dma_layout mt7928_dma_layout = {
+ .tx_data0 = mt792x_dma_ring(MT7925_TXQ_BAND0,
+ MT7925_TX_RING_SIZE,
+ MT_TX_RING_BASE),
+ .tx_mcu = mt792x_dma_ring(MT7925_TXQ_MCU_WM,
+ MT7925_TX_MCU_RING_SIZE,
+ MT_TX_RING_BASE),
+ .tx_fwdl = mt792x_dma_ring(MT7925_TXQ_FWDL,
+ MT7925_TX_FWDL_RING_SIZE,
+ MT_TX_RING_BASE),
+ .tx_done = mt792x_dma_ring(MT7928_RXQ_MCU_WM2,
+ MT7928_RX_MCU_WA_RING_SIZE,
+ MT_RX_EVENT_RING_BASE),
+ .rx_mcu = mt792x_dma_ring(MT7928_RXQ_MCU_WM,
+ MT7925_RX_MCU_RING_SIZE,
+ MT_RX_EVENT_RING_BASE),
+ .rx_data = mt792x_dma_ring(MT7928_RXQ_BAND0,
+ MT7925_RX_RING_SIZE,
+ MT_RX_DATA_RING_BASE),
+};
+
static int mt7927_dma_init(struct mt792x_dev *dev)
{
int ret;
@@ -279,11 +300,62 @@ static int mt7927_dma_init(struct mt792x_dev *dev)
return mt792x_dma_enable(dev);
}
+static void mt7928_dma_shdl_lite_init(struct mt792x_dev *dev)
+{
+ u32 addr, idx, grp1_5_quota, grp15_quota;
+ u32 q2group[8] = {
+ 0x04000000, /* AC00->G0,..., AC03->G4 */
+ 0x04010101, /* AC10->G1,..., AC13->G4 */
+ 0x04020202, /* AC20->G2,..., AC23->G4 */
+ 0x04030303, /* AC30->G3,..., AC33->G4 */
+ 0x00000005, /* ALTX->G5,BMC->G0,BCN->G0 */
+ 0x00000005, /* TGID=1 ALTX->G5 */
+ 0x00000000, /* NAF/NBCN/FIXFID -> G0 */
+ 0x00000005, /* TGID=2 ALTX->G5 */
+ };
+
+ /* RST */
+ mt76_wr(dev, MT_DMASHDL_LITE_MAIN_CONTROL, MT_DMASHDL_LITE_MAIN_CONTROL_SW_RST);
+ /* pse page size 0x10, ple page size 0x7e0 */
+ mt76_wr(dev, MT_DMASHDL_LITE_PAGE_SIZE,
+ FIELD_PREP(MT_DMASHDL_LITE_PSE_PAGE_SIZE_MASK, 0x10) |
+ FIELD_PREP(MT_DMASHDL_LITE_PLE_PAGE_SIZE_MASK, 0x7e0));
+ /* pse max page 8, ple max page 1 */
+ mt76_wr(dev, MT_DMASHDL_LITE_PKT_MAX_SIZE,
+ FIELD_PREP(MT_DMASHDL_LITE_PSE_PKT_MAX_SIZE_MASK, 8) |
+ FIELD_PREP(MT_DMASHDL_LITE_PLE_PKT_MAX_SIZE_MASK, 1));
+ /* SN/UDF check */
+ mt76_wr(dev, MT_DMASHDL_LITE_GROUP_SN_CHK0, 0xffffffff);
+ mt76_wr(dev, MT_DMASHDL_LITE_GROUP_SN_CHK1, 0xffffffff);
+ mt76_wr(dev, MT_DMASHDL_LITE_GROUP_UDF_CHK0, 0xffffffff);
+ mt76_wr(dev, MT_DMASHDL_LITE_GROUP_UDF_CHK1, 0xffffffff);
+ /* q mapping */
+ for (addr = MT_DMASHDL_LITE_Q_MAPPING0, idx = 0;
+ idx < ARRAY_SIZE(q2group);
+ idx++, addr += 4)
+ mt76_wr(dev, addr, q2group[idx]);
+ /* refill, set 0 to enable group 0,1,2,3,4,5 & 15 */
+ mt76_wr(dev, MT_DMASHDL_LITE_GROUP_DISABLE0, 0xffff7fc0);
+ mt76_wr(dev, MT_DMASHDL_LITE_GROUP_DISABLE1, 0xffffffff);
+ /* max/min quota */
+ grp1_5_quota = FIELD_PREP(MT_DMASHDL_LITE_GROUP_MAX_QUOTA_MASK, 0x3f0) |
+ FIELD_PREP(MT_DMASHDL_LITE_GROUP_MIN_QUOTA_MASK, 0x10);
+ grp15_quota = FIELD_PREP(MT_DMASHDL_LITE_GROUP_MAX_QUOTA_MASK, 0x30);
+
+ for (addr = MT_DMASHDL_LITE_GROUP0_QUOTA, idx = 0;
+ idx < DMASHDL_LITE_GROUP_NUM;
+ idx++, addr += 4)
+ mt76_wr(dev, addr, (idx <= 5) ? grp1_5_quota :
+ ((idx == 15) ? grp15_quota : 0));
+}
+
static int mt7925_dma_init(struct mt792x_dev *dev)
{
int ret;
+ const struct mt792x_dma_layout *layout =
+ is_mt7928(&dev->mt76) ? &mt7928_dma_layout : &mt7925_dma_layout;
- ret = mt792x_dma_alloc_queues(dev, &mt7925_dma_layout);
+ ret = mt792x_dma_alloc_queues(dev, layout);
if (ret)
return ret;
@@ -291,6 +363,9 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
if (ret < 0)
return ret;
+ if (is_mt7928(&dev->mt76))
+ mt7928_dma_shdl_lite_init(dev);
+
netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt792x_poll_tx);
napi_enable(&dev->mt76.tx_napi);
@@ -402,14 +477,18 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
if (ret < 0)
return ret;
- ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (ret)
- goto err_free_pci_vec;
-
is_mt7927_hw = (pdev->device == 0x6639 || pdev->device == 0x7927 ||
pdev->device == 0x0738);
is_mt7928_hw = (pdev->device == 0x7928 || pdev->device == 0x7935);
+ if (is_mt7928_hw)
+ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(34));
+ else
+ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+ if (ret)
+ goto err_free_pci_vec;
+
/* MT7927: ASPM L1 causes unreliable WFDMA register access */
if (mt7925_disable_aspm || is_mt7927_hw)
mt76_pci_disable_aspm(pdev);
@@ -499,7 +578,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
if (is_mt7927(&dev->mt76))
ret = mt7927_dma_init(dev);
- else if (is_mt7925(&dev->mt76))
+ else if (is_mt7925(&dev->mt76) || is_mt7928(&dev->mt76))
ret = mt7925_dma_init(dev);
else
ret = -EINVAL;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index 855a53c0748a..253ba72310ec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -108,4 +108,25 @@
#define MT7925_PCIE_MAC_INT_ENABLE MT7925_PCIE_MAC(0x188)
#define MT7925_PCIE_MAC_PM MT7925_PCIE_MAC(0x194)
+#define MT_DMASHDL_LITE_BASE 0x20026200
+#define MT_DMASHDL_LITE(ofs) (MT_DMASHDL_LITE_BASE + (ofs))
+#define MT_DMASHDL_LITE_MAIN_CONTROL MT_DMASHDL_LITE(0x004)
+#define MT_DMASHDL_LITE_MAIN_CONTROL_SW_RST BIT(18)
+#define MT_DMASHDL_LITE_PAGE_SIZE MT_DMASHDL_LITE(0x008)
+#define MT_DMASHDL_LITE_PLE_PAGE_SIZE_MASK GENMASK(12, 0)
+#define MT_DMASHDL_LITE_PSE_PAGE_SIZE_MASK GENMASK(28, 16)
+#define MT_DMASHDL_LITE_PKT_MAX_SIZE MT_DMASHDL_LITE(0x00c)
+#define MT_DMASHDL_LITE_PLE_PKT_MAX_SIZE_MASK GENMASK(12, 0)
+#define MT_DMASHDL_LITE_PSE_PKT_MAX_SIZE_MASK GENMASK(28, 16)
+#define MT_DMASHDL_LITE_GROUP_DISABLE0 MT_DMASHDL_LITE(0x010)
+#define MT_DMASHDL_LITE_GROUP_DISABLE1 MT_DMASHDL_LITE(0x014)
+#define MT_DMASHDL_LITE_GROUP_SN_CHK0 MT_DMASHDL_LITE(0x018)
+#define MT_DMASHDL_LITE_GROUP_SN_CHK1 MT_DMASHDL_LITE(0x01c)
+#define MT_DMASHDL_LITE_GROUP_UDF_CHK0 MT_DMASHDL_LITE(0x020)
+#define MT_DMASHDL_LITE_GROUP_UDF_CHK1 MT_DMASHDL_LITE(0x024)
+#define MT_DMASHDL_LITE_Q_MAPPING0 MT_DMASHDL_LITE(0x028)
+#define MT_DMASHDL_LITE_GROUP0_QUOTA MT_DMASHDL_LITE(0x100)
+#define MT_DMASHDL_LITE_GROUP_MIN_QUOTA_MASK GENMASK(12, 0)
+#define MT_DMASHDL_LITE_GROUP_MAX_QUOTA_MASK GENMASK(28, 16)
+
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
index 4d4c62bb0a77..8ad94fa58340 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
@@ -206,9 +206,38 @@ static void mt7927_wfdma_setup(struct mt792x_dev *dev)
mt76_set(dev, MT_WFDMA0_INT_TX_PRI, 0x7F00);
}
+static void mt7928_dma_prefetch_setup(struct mt792x_dev *dev)
+{
+ /* rx ring */
+ mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x8));
+ mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0080, 0x4));
+ mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x00c0, 0x8));
+ mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x0140, 0x4));
+ mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0x0180, 0x4));
+ mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x01c0, 0x4));
+ mt76_wr(dev, MT_WFDMA0_RX_RING6_EXT_CTRL, PREFETCH(0x0200, 0x4));
+ /* tx ring */
+ mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0240, 0x10));
+ mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0340, 0x10));
+ mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0440, 0x10));
+ mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0540, 0x10));
+ mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x0640, 0x10));
+ mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x0740, 0x10));
+ mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0840, 0x4));
+ mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0880, 0x4));
+}
+
+static void mt7928_wfdma_setup(struct mt792x_dev *dev)
+{
+ mt76_wr(dev, MT_WFDMA0_INT_RX_PRI, 0);
+ mt76_wr(dev, MT_WFDMA0_INT_TX_PRI, 0);
+}
+
static void mt792x_dma_prefetch(struct mt792x_dev *dev)
{
- if (is_mt7927(&dev->mt76)) {
+ if (is_mt7928(&dev->mt76)) {
+ mt7928_dma_prefetch_setup(dev);
+ } else if (is_mt7927(&dev->mt76)) {
mt7927_dma_prefetch_setup(dev);
} else if (is_mt7925(&dev->mt76)) {
mt7925_dma_prefetch_setup(dev);
@@ -250,32 +279,69 @@ static void mt792x_dma_prefetch(struct mt792x_dev *dev)
int mt792x_dma_enable(struct mt792x_dev *dev)
{
- /* configure perfetch settings */
+ u32 addr;
+
+ /* configure prefetch settings */
mt792x_dma_prefetch(dev);
/* reset dma idx */
mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
- if (is_mt7925(&dev->mt76))
+ if (is_mt7925(&dev->mt76) || is_mt7928(&dev->mt76))
mt76_wr(dev, MT_WFDMA0_RST_DRX_PTR, ~0);
/* configure delay interrupt */
mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
- mt76_set(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
- MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
- MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
- MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
- FIELD_PREP(MT_WFDMA0_GLO_CFG_DMA_SIZE, 3) |
- MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK |
- MT_WFDMA0_GLO_CFG_RX_WB_DDONE |
- MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+ if (is_mt7928(&dev->mt76)) {
+ mt76_wr(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
+ MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
+ MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+ FIELD_PREP(MT_WFDMA0_GLO_CFG_DMA_SIZE, 1) |
+ MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK |
+ MT_WFDMA0_GLO_CFG_RX_WB_DDONE |
+ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
+ MT_WFDMA0_GLO_CFG_ADDR_EXT_EN |
+ MT_WFDMA0_GLO_CFG_CSR_LBK_RX_Q_SEL_EN);
+ /* set rxq threshold to 2 */
+ for (addr = MT_WFDMA0_WPDMA_PAUSE_RXQ_TH10;
+ addr <= MT_WFDMA0_WPDMA_PAUSE_RXQ_TH76;
+ addr += 4) {
+ mt76_wr(dev, addr,
+ FIELD_PREP(MT_WFDMA0_WPDMA_PAUSE_RXQ_THXX_L_TH_MASK, 2) |
+ FIELD_PREP(MT_WFDMA0_WPDMA_PAUSE_RXQ_THXX_H_TH_MASK, 2));
+ }
+ mt76_wr(dev, MT_WFDMA0_GLO_CFG_EXT0,
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN |
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_TX_DMASHDL_LITE_EN |
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_RX_WB_KEEP_RSVD |
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN |
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN |
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN |
+ FIELD_PREP(MT_WFDMA0_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK, 3) |
+ FIELD_PREP(MT_WFDMA0_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK, 3) |
+ FIELD_PREP(MT_WFDMA0_GLO_CFG_EXT0_CSR_AXI_AW_OUTSTANDING_NUM_MASK,
+ 8));
+ } else {
+ mt76_set(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
+ MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
+ MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+ FIELD_PREP(MT_WFDMA0_GLO_CFG_DMA_SIZE, 3) |
+ MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK |
+ MT_WFDMA0_GLO_CFG_RX_WB_DDONE |
+ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+ }
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
- if (is_mt7927(&dev->mt76))
+ if (is_mt7928(&dev->mt76))
+ mt7928_wfdma_setup(dev);
+ else if (is_mt7927(&dev->mt76))
mt7927_wfdma_setup(dev);
else if (is_mt7925(&dev->mt76))
mt7925_wfdma_setup(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
index 0e297fd9468a..3587f61e098a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
@@ -331,11 +331,29 @@
#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA
#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
+#define MT_WFDMA0_WPDMA_PAUSE_RXQ_TH10 MT_WFDMA0(0x260)
+#define MT_WFDMA0_WPDMA_PAUSE_RXQ_TH32 MT_WFDMA0(0x264)
+#define MT_WFDMA0_WPDMA_PAUSE_RXQ_TH54 MT_WFDMA0(0x268)
+#define MT_WFDMA0_WPDMA_PAUSE_RXQ_TH76 MT_WFDMA0(0x26c)
+#define MT_WFDMA0_WPDMA_PAUSE_RXQ_THXX_L_TH_MASK GENMASK(11, 0)
+#define MT_WFDMA0_WPDMA_PAUSE_RXQ_THXX_H_TH_MASK GENMASK(27, 16)
+
#define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280)
#define MT_WFDMA0_INT_RX_PRI MT_WFDMA0(0x298)
#define MT_WFDMA0_INT_TX_PRI MT_WFDMA0(0x29c)
#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN BIT(4)
#define MT_WFDMA0_GLO_CFG_EXT0_CSR_TX_DMASHDL_EN BIT(6)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_TX_DMASHDL_LITE_EN BIT(7)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_RX_WB_KEEP_RSVD BIT(10)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN BIT(22)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN BIT(23)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN BIT(29)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK GENMASK(1, 0)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK GENMASK(3, 2)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_AXI_AW_OUTSTANDING_NUM_MASK GENMASK(27, 24)
+
+#define MT_WFDMA0_GLO_CFG_EXT1 MT_WFDMA0(0x2b4)
#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600)
@@ -375,7 +393,6 @@
#define MT_WFDMA_PREFETCH_CFG1 MT_WFDMA_EXT_CSR(0xf4)
#define MT_WFDMA_PREFETCH_CFG2 MT_WFDMA_EXT_CSR(0xf8)
#define MT_WFDMA_PREFETCH_CFG3 MT_WFDMA_EXT_CSR(0xfc)
-#define MT_WFDMA0_GLO_CFG_EXT1 MT_WFDMA0(0x2b4)
#define MT_SWDEF_BASE 0x41f200
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
--
2.45.2
^ permalink raw reply related
* [PATCH 14/20] wifi: mt76: mt7925: add MT7928 irq_map with chip-specific rx masks
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, FC Wei
In-Reply-To: <20260612075313.2578154-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
MT7928 uses different RX interrupt bit assignments (RX_DONE_DATA on
ENA0, RX_DONE_WM on ENA3). Add MT7928-specific irq_map and select
it at probe time based on PCI device ID.
Signed-off-by: FC Wei <fc.wei@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/pci.c | 27 ++++++++++++++++---
.../net/wireless/mediatek/mt76/mt7925/regs.h | 6 +++++
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index e181cd0b6403..6a65c630f85a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -331,6 +331,20 @@ static const struct mt792x_irq_map mt7927_irq_map = {
},
};
+static const struct mt792x_irq_map mt7928_irq_map = {
+ .host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
+ .tx = {
+ .all_complete_mask = MT_INT_TX_DONE_ALL,
+ .mcu_complete_mask = MT_INT_TX_DONE_MCU,
+ },
+ .rx = {
+ .all_complete_mask = MT7928_INT_RX_DONE_ALL,
+ .data_complete_mask = MT7928_INT_RX_DONE_DATA,
+ .wm_complete_mask = MT7928_INT_RX_DONE_WM,
+ .wm2_complete_mask = MT_INT_RX_DONE_WM2,
+ },
+};
+
static int mt7925_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -360,11 +374,11 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
.drv_own = mt792xe_mcu_drv_pmctrl,
.fw_own = mt792xe_mcu_fw_pmctrl,
};
- struct ieee80211_ops *ops;
+ bool is_mt7927_hw, is_mt7928_hw;
struct mt76_bus_ops *bus_ops;
+ struct ieee80211_ops *ops;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
- bool is_mt7927_hw;
u8 features;
int ret;
u16 cmd;
@@ -394,6 +408,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
is_mt7927_hw = (pdev->device == 0x6639 || pdev->device == 0x7927 ||
pdev->device == 0x0738);
+ is_mt7928_hw = (pdev->device == 0x7928 || pdev->device == 0x7935);
/* MT7927: ASPM L1 causes unreliable WFDMA register access */
if (mt7925_disable_aspm || is_mt7927_hw)
@@ -417,9 +432,15 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7925_pcie_ops;
- dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &mt7925_irq_map;
dev->pcie_reg = &mt7925_pcie_reg;
+ if (is_mt7928_hw)
+ dev->irq_map = &mt7928_irq_map;
+ else if (is_mt7927_hw)
+ dev->irq_map = &mt7927_irq_map;
+ else
+ dev->irq_map = &mt7925_irq_map;
+
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index 0bcfd1cf0338..855a53c0748a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -58,6 +58,12 @@
MT7927_INT_RX_DONE_WM | \
MT7927_INT_RX_DONE_WM2)
+#define MT7928_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA0
+#define MT7928_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA3
+#define MT7928_INT_RX_DONE_ALL (MT7928_INT_RX_DONE_DATA | \
+ MT7928_INT_RX_DONE_WM | \
+ MT_INT_RX_DONE_WM2)
+
#define MT_INT_TX_DONE_MCU_WM (HOST_TX_DONE_INT_ENA15 | \
HOST_TX_DONE_INT_ENA17)
--
2.45.2
^ permalink raw reply related
* [PATCH 13/20] wifi: mt76: mt7925: add MT7928 FWDL support
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, FC Wei,
Xiong
In-Reply-To: <20260612075313.2578154-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Add CBMCU and PHY RAM firmware download flow for MT7928. The CBMCU
firmware is loaded in sections before the main WM firmware. Register
MT7928 firmware file names and is_mt7928() chip check.
Signed-off-by: FC Wei <fc.wei@mediatek.com>
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt76_connac.h | 7 +-
.../wireless/mediatek/mt76/mt76_connac_mcu.c | 251 +++++++++++++++++-
.../wireless/mediatek/mt76/mt76_connac_mcu.h | 40 +++
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 15 +-
drivers/net/wireless/mediatek/mt76/mt792x.h | 29 ++
.../net/wireless/mediatek/mt76/mt792x_core.c | 15 ++
6 files changed, 353 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 2aa6078993e9..e21c393bb26d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -174,7 +174,7 @@ extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
static inline bool is_connac3(struct mt76_dev *dev)
{
- return mt76_chip(dev) == 0x7925 || mt76_chip(dev) == 0x7927;
+ return mt76_chip(dev) == 0x7925 || mt76_chip(dev) == 0x7927 || mt76_chip(dev) == 0x7928;
}
static inline bool is_mt7925(struct mt76_dev *dev)
@@ -187,6 +187,11 @@ static inline bool is_mt7927(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7927;
}
+static inline bool is_mt7928(struct mt76_dev *dev)
+{
+ return mt76_chip(dev) == 0x7928;
+}
+
static inline bool is_320mhz_supported(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7927;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 6596c9e198f4..488fe5ef3fbc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -67,7 +67,8 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
(is_connac2(dev) && addr == 0x900000) ||
- (is_connac3(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
+ ((is_mt7925(dev) || is_mt7927(dev)) && (addr == 0x900000 || addr == 0xe0002800)) ||
+ (is_mt7928(dev) && (addr == 0x900000 || addr == 0xe0002000)) ||
(is_mt799x(dev) && addr == 0x900000))
cmd = MCU_CMD(PATCH_START_REQ);
else
@@ -77,6 +78,48 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_init_download);
+int mt76_connac_cb_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get)
+{
+ u8 op = get ? PATCH_SEM_GET : PATCH_SEM_RELEASE;
+ struct {
+ u8 op;
+ u8 reserved[3];
+ } req = {
+ .op = op,
+ };
+
+ return mt76_mcu_send_msg(dev, MCU_CMD(CB_PATCH_SEM_CONTROL),
+ &req, sizeof(req), true);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_cb_mcu_patch_sem_ctrl);
+
+int mt76_connac_cb_mcu_start_patch(struct mt76_dev *dev)
+{
+ struct {
+ __le32 reserved;
+ } req = {
+ .reserved = 0,
+ };
+
+ return mt76_mcu_send_msg(dev, MCU_CMD(CB_PATCH_FINISH_REQ),
+ &req, sizeof(req), true);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_cb_mcu_start_patch);
+
+int mt76_connac_cb_mcu_init_download(struct mt76_dev *dev, u32 len)
+{
+ struct {
+ __le32 addr;
+ __le32 len;
+ } req = {
+ .addr = 0, /* addr is meaningless for cbmcu fwdl */
+ .len = cpu_to_le32(len),
+ };
+
+ return mt76_mcu_send_msg(dev, MCU_CMD(CB_PATCH_START_REQ), &req, sizeof(req), true);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_cb_mcu_init_download);
+
int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy)
{
int len, i, n_max_channels, n_2ch = 0, n_5ch = 0, n_6ch = 0;
@@ -3042,6 +3085,57 @@ mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev,
return mt76_connac_mcu_start_firmware(dev, override, option);
}
+static int
+mt76_connac_mcu_send_phy_ram_firmware(struct mt76_dev *dev,
+ const struct mt76_connac2_fw_trailer *hdr,
+ const u8 *data)
+{
+ int i, offset = 0, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
+ u32 override = 0, option = 0;
+
+ for (i = 0; i < hdr->n_region; i++) {
+ const struct mt76_connac2_fw_region *region;
+ u32 len, addr, mode;
+ int err;
+
+ region = (const void *)((const u8 *)hdr -
+ (hdr->n_region - i) * sizeof(*region));
+ mode = mt76_connac_mcu_gen_dl_mode(dev, region->feature_set,
+ true);
+ len = le32_to_cpu(region->len);
+ addr = le32_to_cpu(region->addr);
+
+ if (region->feature_set & FW_FEATURE_NON_DL)
+ goto next;
+
+ if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
+ override = addr;
+
+ err = mt76_connac_mcu_init_download(dev, addr, len, mode);
+ if (err) {
+ dev_err(dev->dev,
+ "The request to dowload PHY firmware failed.\n");
+ return err;
+ }
+
+ err = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
+ data + offset, len, max_len);
+ if (err) {
+ dev_err(dev->dev, "Failed to send PHY firmware.\n");
+ return err;
+ }
+
+next:
+ offset += len;
+ }
+
+ if (override)
+ option |= FW_START_OVERRIDE;
+ option |= FW_START_WORKING_PDA_DSP;
+
+ return mt76_connac_mcu_start_firmware(dev, override, option);
+}
+
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
const char *fw_wa)
{
@@ -3109,6 +3203,39 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
}
EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);
+int mt76_connac3_load_phy_ram(struct mt76_dev *dev, const char *fw_name)
+{
+ const struct mt76_connac2_fw_trailer *hdr;
+ const struct firmware *fw;
+ int ret;
+
+ ret = request_firmware(&fw, fw_name, dev->dev);
+ if (ret)
+ return ret;
+
+ if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+ dev_err(dev->dev, "Invalid PHY firmware\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
+ dev_info(dev->dev, "PHY Firmware Version: %.10s, Build Time: %.15s\n",
+ hdr->fw_ver, hdr->build_date);
+
+ ret = mt76_connac_mcu_send_phy_ram_firmware(dev, hdr, fw->data);
+ if (ret) {
+ dev_err(dev->dev, "Failed to start PHY firmware\n");
+ goto out;
+ }
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_load_phy_ram);
+
static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
{
u32 mode = DL_MODE_NEED_RSP;
@@ -3222,6 +3349,128 @@ int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
}
EXPORT_SYMBOL_GPL(mt76_connac2_load_patch);
+int mt76_connac3_load_cb_patch(struct mt76_dev *dev, const char *fw_name)
+{
+ const struct mt76_connac3_multi_header_v2_sec_raw_format *sect = NULL;
+ const struct mt76_connac3_multi_header_v2_raw_format *hdr = NULL;
+ int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
+ const struct firmware *fw = NULL;
+ const u8 *dl;
+ u32 len;
+
+ sem = mt76_connac_cb_mcu_patch_sem_ctrl(dev, true);
+ switch (sem) {
+ case CB_PATCH_IS_DL:
+ return 0;
+ case CB_PATCH_GET_SEM_NEED_PATCH:
+ break;
+ default:
+ dev_err(dev->dev, "Failed to get cb patch semaphore %u\n", sem);
+ return -EAGAIN;
+ }
+
+ ret = request_firmware(&fw, fw_name, dev->dev);
+ if (ret)
+ goto out;
+
+ if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+ dev_err(dev->dev, "Invalid firmware\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ hdr = (const void *)fw->data;
+ dev_info(dev->dev, "HW/SW Version: 0x%x, Pack Time: %.21s\n",
+ le32_to_cpu(hdr->patch_ver), hdr->pack_time);
+
+ if (le32_to_cpu(hdr->sec_num) < 2) {
+ dev_err(dev->dev, "Invalid section numbers %u\n",
+ le32_to_cpu(hdr->sec_num));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ sect = &hdr->sects[0];
+ /* check the fw bin basic info */
+ if (((le32_to_cpu(sect->type) & SEC_TYPE_SUBSYS_MASK)
+ != SEC_TYPE_SUBSYS_CBMCU) ||
+ ((le32_to_cpu(sect->type) & SEC_TYPE_SUBSYS_SEC_MASK)
+ != SEC_TYPE_SUBSYS_SEC_IMG_SIGN)) {
+ dev_err(dev->dev, "Invalid CBMCU firmware\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* download global desc + sect map + cert section */
+ len = sizeof(struct mt76_connac3_multi_header_v2_raw_format) -
+ offsetof(struct mt76_connac3_multi_header_v2_raw_format,
+ global_desc_head) +
+ sizeof(struct mt76_connac3_multi_header_v2_sec_raw_format) *
+ le32_to_cpu(hdr->sec_num) +
+ le32_to_cpu(hdr->sects[0].size);
+ dl = &hdr->global_desc_head[0];
+
+ ret = mt76_connac_cb_mcu_init_download(dev, len);
+ if (ret) {
+ dev_err(dev->dev, "Download cb cert section request failed\n");
+ goto out;
+ }
+
+ ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
+ dl, len, max_len);
+ if (ret) {
+ dev_err(dev->dev, "Failed to send cb patch cert section\n");
+ goto out;
+ }
+
+ ret = mt76_connac_cb_mcu_start_patch(dev);
+ if (ret) {
+ dev_err(dev->dev, "CBMCU cert check fail\n");
+ goto out;
+ }
+
+ /* download cbmcu idlm */
+ for (i = 1; i < le32_to_cpu(hdr->sec_num); i++) {
+ dl = (uint8_t *)hdr + le32_to_cpu(hdr->sects[i].offset);
+ len = le32_to_cpu(hdr->sects[i].size);
+
+ ret = mt76_connac_cb_mcu_init_download(dev, len);
+ if (ret) {
+ dev_err(dev->dev,
+ "Download cb section %u request failed\n", i);
+ goto out;
+ }
+
+ ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
+ dl, len, max_len);
+ if (ret) {
+ dev_err(dev->dev,
+ "Failed to send cb patch section %u\n", i);
+ goto out;
+ }
+ }
+
+ ret = mt76_connac_cb_mcu_start_patch(dev);
+ if (ret)
+ dev_err(dev->dev, "Failed to start cb patch\n");
+
+out:
+ sem = mt76_connac_cb_mcu_patch_sem_ctrl(dev, false);
+ switch (sem) {
+ case CB_PATCH_REL_SEM_SUCCESS:
+ break;
+ default:
+ ret = -EAGAIN;
+ dev_err(dev->dev, "Failed to release cb patch semaphore\n");
+ break;
+ }
+
+ release_firmware(fw);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_load_cb_patch);
+
int mt76_connac2_mcu_fill_message(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, int *wait_seq)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 6d0429f40b0f..5674090961d4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -35,6 +35,12 @@
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
+#define SEC_TYPE_SUBSYS_MASK GENMASK(23, 16)
+#define SEC_TYPE_SUBSYS_CBMCU BIT(16)
+
+#define SEC_TYPE_SUBSYS_SEC_MASK GENMASK(15, 0)
+#define SEC_TYPE_SUBSYS_SEC_IMG_SIGN 0x05
+
enum {
FW_TYPE_DEFAULT = 0,
FW_TYPE_CLC = 2,
@@ -193,6 +199,25 @@ struct mt76_connac2_fw_region {
u8 rsv1[14];
} __packed;
+struct mt76_connac3_multi_header_v2_sec_raw_format {
+ __le32 type;
+ __le32 offset;
+ __le32 size;
+ u8 spec[52];
+} __packed;
+
+struct mt76_connac3_multi_header_v2_raw_format {
+ u8 pack_time[20];
+ u8 chip_id_eco_ver[8];
+ __le32 patch_ver;
+ u8 global_desc_head[4];
+ __le32 global_subsys;
+ u8 rsv2[4];
+ __le32 sec_num;
+ u8 rsv3[48];
+ struct mt76_connac3_multi_header_v2_sec_raw_format sects[];
+} __packed;
+
struct tlv {
__le16 tag;
__le16 len;
@@ -1104,6 +1129,13 @@ enum {
PATCH_REL_SEM_SUCCESS
};
+enum {
+ CB_PATCH_GET_SEM_NEED_PATCH,
+ CB_PATCH_IS_DL,
+ CB_PATCH_NO_SEM_NEED_PATCH,
+ CB_PATCH_REL_SEM_SUCCESS
+};
+
enum {
FW_STATE_INITIAL,
FW_STATE_FW_DOWNLOAD,
@@ -1332,6 +1364,9 @@ enum {
MCU_CMD_PATCH_START_REQ = 0x05,
MCU_CMD_PATCH_FINISH_REQ = 0x07,
MCU_CMD_PATCH_SEM_CONTROL = 0x10,
+ MCU_CMD_CB_PATCH_SEM_CONTROL = 0x30,
+ MCU_CMD_CB_PATCH_START_REQ = 0x31,
+ MCU_CMD_CB_PATCH_FINISH_REQ = 0x32,
MCU_CMD_WA_PARAM = 0xc4,
MCU_CMD_EXT_CID = 0xed,
MCU_CMD_FW_SCATTER = 0xee,
@@ -2018,6 +2053,9 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
u32 mode);
int mt76_connac_mcu_start_patch(struct mt76_dev *dev);
int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
+int mt76_connac_cb_mcu_init_download(struct mt76_dev *dev, u32 len);
+int mt76_connac_cb_mcu_start_patch(struct mt76_dev *dev);
+int mt76_connac_cb_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option);
void mt76_connac_mcu_build_rnr_scan_param(struct mt76_dev *mdev,
@@ -2101,7 +2139,9 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb);
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
const char *fw_wa);
+int mt76_connac3_load_phy_ram(struct mt76_dev *dev, const char *fw_name);
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name);
+int mt76_connac3_load_cb_patch(struct mt76_dev *dev, const char *fw_name);
int mt76_connac2_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq);
#endif /* __MT76_CONNAC_MCU_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index e94fa544ff20..0b4ca5cf5734 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -26,13 +26,24 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
}
rxd = (struct mt7925_mcu_rxd *)skb->data;
- if (seq != rxd->seq)
- return -EAGAIN;
+ if (seq != rxd->seq) {
+ if (!is_mt7928(mdev))
+ return -EAGAIN;
+ else if (is_mt7928(mdev) &&
+ cmd != MCU_CMD(CB_PATCH_SEM_CONTROL) &&
+ cmd != MCU_CMD(CB_PATCH_FINISH_REQ))
+ return -EAGAIN;
+ }
if (cmd == MCU_CMD(PATCH_SEM_CONTROL) ||
cmd == MCU_CMD(PATCH_FINISH_REQ)) {
skb_pull(skb, sizeof(*rxd) - 4);
ret = *skb->data;
+ } else if (is_mt7928(mdev) &&
+ (cmd == MCU_CMD(CB_PATCH_SEM_CONTROL) ||
+ cmd == MCU_CMD(CB_PATCH_FINISH_REQ))) {
+ skb_pull(skb, sizeof(*rxd) - 4);
+ ret = *skb->data;
} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||
cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||
cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 7d014de030c4..8c7ecd3ce126 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -47,6 +47,7 @@
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
#define MT7927_FIRMWARE_WM "mediatek/mt7927/WIFI_RAM_CODE_MT6639_2_1.bin"
+#define MT7928_FIRMWARE_WM "mediatek/mt7928/WIFI_RAM_CODE_MT7935_1_1.bin"
#define MT7902_ROM_PATCH "mediatek/WIFI_MT7902_patch_mcu_1_1_hdr.bin"
#define MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"
@@ -54,6 +55,10 @@
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
#define MT7925_ROM_PATCH "mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin"
#define MT7927_ROM_PATCH "mediatek/mt7927/WIFI_MT6639_PATCH_MCU_2_1_hdr.bin"
+#define MT7928_ROM_PATCH "mediatek/mt7928/WIFI_MT7935_PATCH_MCU_1_1_hdr.bin"
+
+#define MT7928_CB_ROM_PATCH "mediatek/mt7928/CBMCU_CODE_MT7935_1_1.bin"
+#define MT7928_PHY_RAM "mediatek/mt7928/WIFI_MT7935_PHY_RAM_CODE_1_1.bin"
#define MT792x_SDIO_HDR_TX_BYTES GENMASK(15, 0)
#define MT792x_SDIO_HDR_PKT_TYPE GENMASK(17, 16)
@@ -494,6 +499,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
return MT7925_FIRMWARE_WM;
case 0x7927:
return MT7927_FIRMWARE_WM;
+ case 0x7928:
+ return MT7928_FIRMWARE_WM;
default:
return MT7921_FIRMWARE_WM;
}
@@ -512,11 +519,33 @@ static inline char *mt792x_patch_name(struct mt792x_dev *dev)
return MT7925_ROM_PATCH;
case 0x7927:
return MT7927_ROM_PATCH;
+ case 0x7928:
+ return MT7928_ROM_PATCH;
default:
return MT7921_ROM_PATCH;
}
}
+static inline char *mt792x_cb_patch_name(struct mt792x_dev *dev)
+{
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7928:
+ return MT7928_CB_ROM_PATCH;
+ default:
+ return NULL;
+ }
+}
+
+static inline char *mt792x_phy_ram_name(struct mt792x_dev *dev)
+{
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7928:
+ return MT7928_PHY_RAM;
+ default:
+ return NULL;
+ }
+}
+
int mt792x_load_firmware(struct mt792x_dev *dev);
/* usb */
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
index b50825eccdaf..9bd679b7e889 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
@@ -985,6 +985,15 @@ int mt792x_load_firmware(struct mt792x_dev *dev)
dev_warn(dev->mt76.dev,
"MCU is not ready for firmware download\n");
+ if (is_mt7928(&dev->mt76)) {
+ dev_info(dev->mt76.dev, "Loading CB firmware patch: %s\n",
+ mt792x_cb_patch_name(dev));
+ ret = mt76_connac3_load_cb_patch(&dev->mt76, mt792x_cb_patch_name(dev));
+ if (ret)
+ return ret;
+ }
+
+ dev_info(dev->mt76.dev, "Loading firmware patch: %s\n", mt792x_patch_name(dev));
ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));
if (ret)
return ret;
@@ -996,6 +1005,12 @@ int mt792x_load_firmware(struct mt792x_dev *dev)
ret = __mt792x_mcu_drv_pmctrl(dev);
}
+ if (is_mt7928(&dev->mt76)) {
+ ret = mt76_connac3_load_phy_ram(&dev->mt76, mt792x_phy_ram_name(dev));
+ if (ret)
+ return ret;
+ }
+
ret = mt76_connac2_load_ram(&dev->mt76, mt792x_ram_name(dev), NULL);
if (ret)
return ret;
--
2.45.2
^ permalink raw reply related
* [PATCH 11/20] wifi: mt76: connac3: update basic rate table starting index
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
From: Emery Hsin <emery.hsin@mediatek.com>
Change MT792x_BASIC_RATES_TBL index from 11 to 14 to match the latest
connac3 firmware rate table layout.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt792x.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index b8dc7ce38c87..7d014de030c4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -33,7 +33,7 @@
#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
-#define MT792x_BASIC_RATES_TBL 11
+#define MT792x_BASIC_RATES_TBL 14
#define MT792x_WATCHDOG_TIME (HZ / 4)
--
2.45.2
^ permalink raw reply related
* [PATCH 12/20] wifi: mt76: mt7925: fix MMIO dynamic remap window size
From: JB Tsai @ 2026-06-12 7:53 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075313.2578154-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Fix the 0x7c500000 remap entry window size from 0x2000000 (32MB) to
0x200000 (2MB) to match the actual addressable range.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 61349c260b12..e181cd0b6403 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -161,7 +161,7 @@ static u32 __mt7925_reg_addr(struct mt792x_dev *dev, u32 addr)
{ 0x7c060000, 0x0e0000, 0x0010000 }, /* CONN_INFRA, conn_host_csr_top */
{ 0x7c000000, 0x0f0000, 0x0010000 }, /* CONN_INFRA */
{ 0x70020000, 0x1f0000, 0x0010000 }, /* Reserved for CBTOP, can't switch */
- { 0x7c500000, 0x060000, 0x2000000 }, /* remap */
+ { 0x7c500000, 0x060000, 0x200000 }, /* remap */
{ 0x0, 0x0, 0x0 } /* End */
};
int i;
--
2.45.2
^ permalink raw reply related
* [PATCH 10/20] wifi: mt76: mt792x: add tx_done ring to common DMA queue allocation
From: JB Tsai @ 2026-06-12 7:51 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075136.2577553-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Add a tx_done field to mt792x_dma_layout and extend
mt792x_dma_alloc_queues() to allocate the MT_RXQ_MCU_WA queue when
tx_done.ring_base is configured.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt792x.h | 1 +
drivers/net/wireless/mediatek/mt76/mt792x_dma.c | 11 +++++++++++
2 files changed, 12 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index eacee63e13f3..b8dc7ce38c87 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -217,6 +217,7 @@ struct mt792x_dma_layout {
struct mt792x_dma_ring tx_data0;
struct mt792x_dma_ring tx_mcu;
struct mt792x_dma_ring tx_fwdl;
+ struct mt792x_dma_ring tx_done;
struct mt792x_dma_ring rx_data;
struct mt792x_dma_ring rx_mcu;
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
index b090ba9cd676..4d4c62bb0a77 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
@@ -122,6 +122,17 @@ int mt792x_dma_alloc_queues(struct mt792x_dev *dev,
if (ret)
return ret;
+ /* tx done */
+ if (layout->tx_done.ring_base) {
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
+ layout->tx_done.qid,
+ layout->tx_done.n_desc,
+ MT_RX_BUF_SIZE,
+ layout->tx_done.ring_base);
+ if (ret)
+ return ret;
+ }
+
/* rx event */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
layout->rx_mcu.qid,
--
2.45.2
^ permalink raw reply related
* [PATCH 08/20] wifi: mt76: mt792x: rename WFDMA DMASHDL enable bit to follow the convention
From: JB Tsai @ 2026-06-12 7:51 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075136.2577553-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Rename MT_WFDMA0_CSR_TX_DMASHDL_ENABLE to
MT_WFDMA0_GLO_CFG_EXT0_CSR_TX_DMASHDL_EN to follow the register
naming convention (parent register name as prefix).
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt792x_dma.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt792x_regs.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
index 2947504ef20b..b090ba9cd676 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
@@ -386,7 +386,7 @@ int mt792x_dma_disable(struct mt792x_dev *dev, bool force)
/* disable dmashdl */
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
- MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
+ MT_WFDMA0_GLO_CFG_EXT0_CSR_TX_DMASHDL_EN);
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
if (force) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
index 6d174b158915..0e297fd9468a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
@@ -335,7 +335,7 @@
#define MT_WFDMA0_INT_RX_PRI MT_WFDMA0(0x298)
#define MT_WFDMA0_INT_TX_PRI MT_WFDMA0(0x29c)
#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
-#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6)
+#define MT_WFDMA0_GLO_CFG_EXT0_CSR_TX_DMASHDL_EN BIT(6)
#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600)
--
2.45.2
^ permalink raw reply related
* [PATCH 07/20] wifi: mt76: mt7925: add per-chip PCIe register definitions
From: JB Tsai @ 2026-06-12 7:51 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, Xiong
In-Reply-To: <20260612075136.2577553-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Add MT7925_PCIE_MAC_{INT_ENABLE,PM} macros and mt7925_pcie_reg
struct. Update all PCIe register accesses in pci.c, pci_mac.c, and
pci_mcu.c to use dev->pcie_reg->{imask,pm}.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 15 ++++++++++-----
.../net/wireless/mediatek/mt76/mt7925/pci_mac.c | 4 ++--
.../net/wireless/mediatek/mt76/mt7925/pci_mcu.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7925/regs.h | 5 +++++
4 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 8a4fb53c718f..61349c260b12 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -298,6 +298,11 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
return mt792x_dma_enable(dev);
}
+static const struct mt792x_pcie_reg mt7925_pcie_reg = {
+ .imask = MT7925_PCIE_MAC_INT_ENABLE,
+ .pm = MT7925_PCIE_MAC_PM,
+};
+
static const struct mt792x_irq_map mt7925_irq_map = {
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
.tx = {
@@ -413,6 +418,8 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
dev->fw_features = features;
dev->hif_ops = &mt7925_pcie_ops;
dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &mt7925_irq_map;
+ dev->pcie_reg = &mt7925_pcie_reg;
+
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
@@ -462,8 +469,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
goto err_free_dev;
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
-
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ mt76_wr(dev, dev->pcie_reg->imask, 0xff);
ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
@@ -564,8 +570,7 @@ static int mt7925_pci_suspend(struct device *device)
/* disable interrupt */
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
-
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
+ mt76_wr(dev, dev->pcie_reg->imask, 0x0);
synchronize_irq(pdev->irq);
tasklet_kill(&mdev->irq_tasklet);
@@ -615,7 +620,7 @@ static int _mt7925_pci_resume(struct device *device, bool restore)
mt792x_wpdma_reinit_cond(dev);
/* enable interrupt */
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ mt76_wr(dev, dev->pcie_reg->imask, 0xff);
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask |
dev->irq_map->rx.all_complete_mask |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
index d288739e1307..8477d21abc66 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
@@ -78,7 +78,7 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
+ mt76_wr(dev, dev->pcie_reg->imask, 0x0);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
@@ -121,7 +121,7 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
dev->irq_map->tx.all_complete_mask |
dev->irq_map->rx.all_complete_mask |
MT_INT_MCU_CMD);
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ mt76_wr(dev, dev->pcie_reg->imask, 0xff);
err = mt792xe_mcu_fw_pmctrl(dev);
if (err)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
index 6cceff88c656..72707eddc3db 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
@@ -43,7 +43,7 @@ int mt7925e_mcu_init(struct mt792x_dev *dev)
if (err)
return err;
- mt76_rmw_field(dev, MT_PCIE_MAC_PM, MT_PCIE_MAC_PM_L0S_DIS, 1);
+ mt76_rmw_field(dev, dev->pcie_reg->pm, MT_PCIE_MAC_PM_L0S_DIS, 1);
err = mt7925_run_firmware(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index bb5969689337..85adde2ad597 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -97,4 +97,9 @@
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
+#define MT7925_PCIE_MAC_BASE 0x10000
+#define MT7925_PCIE_MAC(ofs) (MT7925_PCIE_MAC_BASE + (ofs))
+#define MT7925_PCIE_MAC_INT_ENABLE MT7925_PCIE_MAC(0x188)
+#define MT7925_PCIE_MAC_PM MT7925_PCIE_MAC(0x194)
+
#endif
--
2.45.2
^ permalink raw reply related
* [PATCH 09/20] wifi: mt76: mt7925: rename WTBL registers to chip-specific format
From: JB Tsai @ 2026-06-12 7:51 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075136.2577553-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Rename MT_WTBLON_TOP_WDUCR and MT_WTBL_UPDATE to MT7925-prefixed
versions since MT7928 uses different WTBL register offsets.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt7925/mac.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7925/regs.h | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 5dd895c3f205..44d5a1e7e415 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -12,10 +12,10 @@
bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask)
{
- mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
+ mt76_rmw(dev, MT7925_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
- return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY,
+ return mt76_poll(dev, MT7925_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY,
0, 5000);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.h b/drivers/net/wireless/mediatek/mt76/mt7925/mac.h
index 83ea9021daea..67148c87de76 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.h
@@ -14,7 +14,7 @@
static inline u32 mt7925_mac_wtbl_lmac_addr(struct mt792x_dev *dev, u16 wcid, u8 dw)
{
- mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
+ mt76_wr(dev, MT7925_WTBLON_TOP_WDUCR,
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
return MT_WTBL_LMAC_OFFS(wcid, dw);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index 85adde2ad597..0bcfd1cf0338 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -90,10 +90,10 @@
#define MT_WFSYS_SW_RST_B 0x7c000140
-#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370)
+#define MT7925_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370)
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0)
-#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x380)
+#define MT7925_WTBL_UPDATE MT_WTBLON_TOP(0x380)
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
--
2.45.2
^ permalink raw reply related
* [PATCH 06/20] wifi: mt76: connac2: add per-chip PCIe register definitions
From: JB Tsai @ 2026-06-12 7:51 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai, Xiong
From: Emery Hsin <emery.hsin@mediatek.com>
Add MT_PCIE_MAC_{INT_ENABLE,PM} definitions to mt7921/regs.h and
wire up mt7921_pcie_reg in mt7921_pci_probe() to provide connac2
series chips with their own PCIe register definitions.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Xiong <xiong.huang@mediatek.com>
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 5 +++++
drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 067f6b4142b6..a93cdc1f1c93 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -285,6 +285,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
.drv_own = mt792xe_mcu_drv_pmctrl,
.fw_own = mt792xe_mcu_fw_pmctrl,
};
+ static const struct mt792x_pcie_reg mt7921_pcie_reg = {
+ .imask = MT_PCIE_MAC_INT_ENABLE,
+ .pm = MT_PCIE_MAC_PM,
+ };
static const struct mt792x_irq_map irq_map = {
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
.tx = {
@@ -354,6 +358,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
dev->fw_features = features;
dev->hif_ops = &mt7921_pcie_ops;
+ dev->pcie_reg = &mt7921_pcie_reg;
dev->irq_map = &irq_map;
mt76_mmio_init(&dev->mt76, regs);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
index 4d9eaf1e0692..75b4e81c7224 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
@@ -78,4 +78,9 @@
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12)
+#define MT_PCIE_MAC_BASE 0x10000
+#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
+#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
+#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194)
+
#endif
--
2.45.2
^ permalink raw reply related
* [PATCH 03/20] wifi: mt76: mt7925: replace shared rx irq masks with per-chip definitions
From: JB Tsai @ 2026-06-12 7:50 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075042.2577193-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Replace shared MT_INT_RX_DONE_* macros with chip-specific
MT7925_INT_RX_DONE_{DATA,WM,WM2,ALL} and populate all_complete_mask
in mt7925_irq_map. Update resume and mac_reset paths accordingly.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/pci.c | 33 ++++++++++---------
.../wireless/mediatek/mt76/mt7925/pci_mac.c | 4 +--
.../net/wireless/mediatek/mt76/mt7925/regs.h | 9 ++---
3 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index ea64303283ed..95a0bd615167 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -298,6 +298,20 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
return mt792x_dma_enable(dev);
}
+static const struct mt792x_irq_map mt7925_irq_map = {
+ .host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
+ .tx = {
+ .all_complete_mask = MT_INT_TX_DONE_ALL,
+ .mcu_complete_mask = MT_INT_TX_DONE_MCU,
+ },
+ .rx = {
+ .all_complete_mask = MT7925_INT_RX_DONE_ALL,
+ .data_complete_mask = MT7925_INT_RX_DONE_DATA,
+ .wm_complete_mask = MT7925_INT_RX_DONE_WM,
+ .wm2_complete_mask = MT_INT_RX_DONE_WM2,
+ },
+};
+
static const struct mt792x_irq_map mt7927_irq_map = {
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
.tx = {
@@ -339,17 +353,6 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
.drv_own = mt792xe_mcu_drv_pmctrl,
.fw_own = mt792xe_mcu_fw_pmctrl,
};
- static const struct mt792x_irq_map irq_map = {
- .host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
- .tx = {
- .all_complete_mask = MT_INT_TX_DONE_ALL,
- .mcu_complete_mask = MT_INT_TX_DONE_MCU,
- },
- .rx = {
- .data_complete_mask = HOST_RX_DONE_INT_ENA2,
- .wm_complete_mask = HOST_RX_DONE_INT_ENA0,
- },
- };
struct ieee80211_ops *ops;
struct mt76_bus_ops *bus_ops;
struct mt792x_dev *dev;
@@ -407,7 +410,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7925_pcie_ops;
- dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &irq_map;
+ dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &mt7925_irq_map;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
@@ -456,7 +459,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_free_dev;
- mt76_wr(dev, irq_map.host_irq_enable, 0);
+ mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
@@ -613,9 +616,7 @@ static int _mt7925_pci_resume(struct device *device, bool restore)
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask |
- dev->irq_map->rx.data_complete_mask |
- dev->irq_map->rx.wm_complete_mask |
- dev->irq_map->rx.wm2_complete_mask |
+ dev->irq_map->rx.all_complete_mask |
MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
index 97683949a305..d288739e1307 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
@@ -119,9 +119,7 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
mt76_wr(dev, dev->irq_map->host_irq_enable,
dev->irq_map->tx.all_complete_mask |
- dev->irq_map->rx.data_complete_mask |
- dev->irq_map->rx.wm_complete_mask |
- dev->irq_map->rx.wm2_complete_mask |
+ dev->irq_map->rx.all_complete_mask |
MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index 24985bba1b90..aed90cc82858 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -43,11 +43,12 @@
#define HOST_TX_DONE_INT_ENA17 BIT(27)
/* WFDMA interrupt */
-#define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2
-#define MT_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA0
#define MT_INT_RX_DONE_WM2 HOST_RX_DONE_INT_ENA1
-#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_DATA | \
- MT_INT_RX_DONE_WM | \
+
+#define MT7925_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2
+#define MT7925_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA0
+#define MT7925_INT_RX_DONE_ALL (MT7925_INT_RX_DONE_DATA | \
+ MT7925_INT_RX_DONE_WM | \
MT_INT_RX_DONE_WM2)
#define MT_INT_TX_DONE_MCU_WM (HOST_TX_DONE_INT_ENA15 | \
--
2.45.2
^ permalink raw reply related
* [PATCH 05/20] wifi: mt76: mt792x: replace shared PCIe MAC macros with per-chip struct
From: JB Tsai @ 2026-06-12 7:50 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075042.2577193-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Replace hardcoded MT_PCIE_MAC_INT_ENABLE and MT_PCIE_MAC_PM macros
with a per-chip mt792x_pcie_reg struct. Remove the shared macros
from mt792x_regs.h and update mt792x_wpdma_reinit_cond() to use
dev->pcie_reg.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt792x.h | 6 ++++++
drivers/net/wireless/mediatek/mt76/mt792x_dma.c | 6 ++++--
drivers/net/wireless/mediatek/mt76/mt792x_regs.h | 4 ----
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 83c729f8bb76..eacee63e13f3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -238,6 +238,11 @@ struct mt792x_hif_ops {
int (*fw_own)(struct mt792x_dev *dev);
};
+struct mt792x_pcie_reg {
+ u32 imask;
+ u32 pm;
+};
+
struct mt792x_dev {
union { /* must be first */
struct mt76_dev mt76;
@@ -273,6 +278,7 @@ struct mt792x_dev {
struct mt76_connac_coredump coredump;
const struct mt792x_hif_ops *hif_ops;
const struct mt792x_irq_map *irq_map;
+ const struct mt792x_pcie_reg *pcie_reg;
struct work_struct ipv6_ns_work;
struct delayed_work mlo_pm_work;
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
index 946ff6d58954..2947504ef20b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
@@ -345,7 +345,8 @@ int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev)
if (mt792x_dma_need_reinit(dev)) {
/* disable interrutpts */
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
+ if (dev->pcie_reg)
+ mt76_wr(dev, dev->pcie_reg->imask, 0x0);
err = mt792x_wpdma_reset(dev, false);
if (err) {
@@ -354,7 +355,8 @@ int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev)
}
/* enable interrutpts */
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ if (dev->pcie_reg)
+ mt76_wr(dev, dev->pcie_reg->imask, 0xff);
pm->stats.lp_wake++;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
index 4cd5b33b640e..6d174b158915 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
@@ -415,10 +415,6 @@
#define MT_HW_EMI_CTL 0x18011100
#define MT_HW_EMI_CTL_SLPPROT_EN BIT(1)
-#define MT_PCIE_MAC_BASE 0x10000
-#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
-#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
-#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194)
#define MT_PCIE_MAC_PM_L0S_DIS BIT(8)
#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs))
--
2.45.2
^ permalink raw reply related
* [PATCH 04/20] wifi: mt76: mt7925: add MT7927 per-chip rx irq definitions
From: JB Tsai @ 2026-06-12 7:50 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075042.2577193-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Add MT7927_INT_RX_DONE_{DATA,WM,WM2,ALL} macros and populate
all_complete_mask in mt7927_irq_map. MT7927 maps RX_DONE_DATA to
ENA4 and RX_DONE_WM to ENA6, differing from MT7925.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 8 +++++---
drivers/net/wireless/mediatek/mt76/mt7925/regs.h | 7 +++++++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 95a0bd615167..8a4fb53c718f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -319,11 +319,13 @@ static const struct mt792x_irq_map mt7927_irq_map = {
.mcu_complete_mask = MT_INT_TX_DONE_MCU,
},
.rx = {
- .data_complete_mask = MT7927_RX_DONE_INT_ENA4,
- .wm_complete_mask = MT7927_RX_DONE_INT_ENA6,
- .wm2_complete_mask = MT7927_RX_DONE_INT_ENA7,
+ .all_complete_mask = MT7927_INT_RX_DONE_ALL,
+ .data_complete_mask = MT7927_INT_RX_DONE_DATA,
+ .wm_complete_mask = MT7927_INT_RX_DONE_WM,
+ .wm2_complete_mask = MT7927_INT_RX_DONE_WM2,
},
};
+
static int mt7925_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
index aed90cc82858..bb5969689337 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h
@@ -51,6 +51,13 @@
MT7925_INT_RX_DONE_WM | \
MT_INT_RX_DONE_WM2)
+#define MT7927_INT_RX_DONE_DATA MT7927_RX_DONE_INT_ENA4
+#define MT7927_INT_RX_DONE_WM MT7927_RX_DONE_INT_ENA6
+#define MT7927_INT_RX_DONE_WM2 MT7927_RX_DONE_INT_ENA7
+#define MT7927_INT_RX_DONE_ALL (MT7927_INT_RX_DONE_DATA | \
+ MT7927_INT_RX_DONE_WM | \
+ MT7927_INT_RX_DONE_WM2)
+
#define MT_INT_TX_DONE_MCU_WM (HOST_TX_DONE_INT_ENA15 | \
HOST_TX_DONE_INT_ENA17)
--
2.45.2
^ permalink raw reply related
* [PATCH 01/20] wifi: mt76: mt792x: consolidate rx interrupt masks into all_complete_mask
From: JB Tsai @ 2026-06-12 7:50 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
From: Emery Hsin <emery.hsin@mediatek.com>
Add all_complete_mask to irq_map rx sub-struct and use it in
mt792x_irq_tasklet() and mt792x_dma_enable() to replace individual
per-ring mask OR expressions.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt792x.h | 1 +
drivers/net/wireless/mediatek/mt76/mt792x_dma.c | 8 ++------
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 70073b43af54..83c729f8bb76 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -200,6 +200,7 @@ struct mt792x_irq_map {
u32 mcu_complete_mask;
} tx;
struct {
+ u32 all_complete_mask;
u32 data_complete_mask;
u32 wm_complete_mask;
u32 wm2_complete_mask;
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
index fc326447c792..946ff6d58954 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
@@ -39,9 +39,7 @@ void mt792x_irq_tasklet(unsigned long data)
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
- mask |= intr & (irq_map->rx.data_complete_mask |
- irq_map->rx.wm_complete_mask |
- irq_map->rx.wm2_complete_mask);
+ mask |= intr & irq_map->rx.all_complete_mask;
if (intr & dev->irq_map->tx.mcu_complete_mask)
mask |= dev->irq_map->tx.mcu_complete_mask;
@@ -276,9 +274,7 @@ int mt792x_dma_enable(struct mt792x_dev *dev)
/* enable interrupts for TX/RX rings */
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask |
- dev->irq_map->rx.data_complete_mask |
- dev->irq_map->rx.wm2_complete_mask |
- dev->irq_map->rx.wm_complete_mask |
+ dev->irq_map->rx.all_complete_mask |
MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
--
2.45.2
^ permalink raw reply related
* [PATCH 02/20] wifi: mt76: connac2: apply new rx all_complete_mask
From: JB Tsai @ 2026-06-12 7:50 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, emery.hsin, jb.tsai
In-Reply-To: <20260612075042.2577193-1-jb.tsai@mediatek.com>
From: Emery Hsin <emery.hsin@mediatek.com>
Populate all_complete_mask in MT7921 irq_map and update pci_resume()
and mac_reset() to use irq_map->rx.all_complete_mask instead of the
hardcoded MT_INT_RX_DONE_ALL macro.
This is a preparation patch before enabling MT7928 PCIe support.
Signed-off-by: Emery Hsin <emery.hsin@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 4 +++-
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 49a37185f056..067f6b4142b6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -292,6 +292,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
.mcu_complete_mask = MT_INT_TX_DONE_MCU,
},
.rx = {
+ .all_complete_mask = MT_INT_RX_DONE_ALL,
.data_complete_mask = MT_INT_RX_DONE_DATA,
.wm_complete_mask = MT_INT_RX_DONE_WM,
.wm2_complete_mask = MT_INT_RX_DONE_WM2,
@@ -559,7 +560,8 @@ static int mt7921_pci_resume(struct device *device)
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask |
- MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
+ dev->irq_map->rx.all_complete_mask |
+ MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
/* put dma enabled */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
index 0db7acb3a637..98b3469ac597 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
@@ -96,7 +96,8 @@ int mt7921e_mac_reset(struct mt792x_dev *dev)
mt76_wr(dev, dev->irq_map->host_irq_enable,
dev->irq_map->tx.all_complete_mask |
- MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
+ dev->irq_map->rx.all_complete_mask |
+ MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
err = mt7921e_driver_own(dev);
--
2.45.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox