* [PATCH] net: airoha: Fix always-true condition in PPE1 queue reservation loop
From: Wayen.Yan @ 2026-06-13 0:23 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In airoha_fe_pse_ports_init(), the inner condition for PPE1 queue
reservation is identical to the for-loop bound, making it always true
and the else branch dead code:
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE1]; q++) {
if (q < pse_port_num_queues[FE_PSE_PORT_PPE1]) /* always true */
set RSV_PAGES;
else
set 0; /* unreachable */
}
The intended behavior is to reserve pages only for the first half of
the queues, matching the PPE2 implementation on line 334 which
correctly uses the /2 divisor. Fix the PPE1 condition accordingly.
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Wayen.Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 31cdb11..999f517 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -311,7 +311,7 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)
PSE_QUEUE_RSV_PAGES);
/* PPE1 */
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE1]; q++) {
- if (q < pse_port_num_queues[FE_PSE_PORT_PPE1])
+ if (q < pse_port_num_queues[FE_PSE_PORT_PPE1] / 2)
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE1, q,
PSE_QUEUE_RSV_PAGES);
else
--
2.51.0
^ permalink raw reply related
* [PATCH] net: airoha: Fix non-standard return value in airoha_ppe_get_wdma_info()
From: Wayen.Yan @ 2026-06-13 0:22 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
airoha_ppe_get_wdma_info() returns -1 when the last path in the
forwarding path stack is not of type DEV_PATH_MTK_WDMA. This is not
a standard kernel error code. Replace it with -EINVAL since the
input path type is invalid from the caller's perspective.
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Wayen.Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_ppe.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 5c9dff6..7260177 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -264,7 +264,7 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
path = &stack.path[stack.num_paths - 1];
if (path->type != DEV_PATH_MTK_WDMA)
- return -1;
+ return -EINVAL;
info->idx = path->mtk_wdma.wdma_idx;
info->bss = path->mtk_wdma.bss;
--
2.51.0
^ permalink raw reply related
* Re: [PATCH 00/10] ASoC: mediatek: Use guard() for mutex & spin locks
From: Mark Brown @ 2026-06-11 19:59 UTC (permalink / raw)
To: Matthias Brugger, phucduc.bui
Cc: Liam Girdwood, AngeloGioacchino Del Regno, Linus Walleij,
Bartosz Golaszewski, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-kernel, linux-mediatek, linux-kernel, linux-gpio
In-Reply-To: <20260610102021.83273-1-phucduc.bui@gmail.com>
On Wed, 10 Jun 2026 17:20:11 +0700, phucduc.bui@gmail.com wrote:
> ASoC: mediatek: Use guard() for mutex & spin locks
>
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Hi all,
>
> This series converts mutex and spinlock handling in Mediatek ASoC drivers
> to use guard() helpers.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2
Thanks!
[01/10] ASoC: mediatek: common: mtk-afe-fe-dai: Use guard() for mutex locks
https://git.kernel.org/broonie/sound/c/9475859429e4
[02/10] ASoC: mediatek: common: mtk-btcvsd: Use guard() for spin locks
https://git.kernel.org/broonie/sound/c/c69724b714c5
[03/10] ASoC: mediatek: mt8186: mt8186-afe-gpio: Use guard() for mutex locks
https://git.kernel.org/broonie/sound/c/1e9f4587c873
[04/10] ASoC: mediatek: mt8188: mt8188-afe-clk: Use guard() for spin locks
https://git.kernel.org/broonie/sound/c/cc29c31e87fc
[05/10] ASoC: mediatek: mt8192: mt8192-afe-gpio: Use guard() for mutex locks
https://git.kernel.org/broonie/sound/c/14edf39daefb
[06/10] ASoC: mediatek: mt8195: mt8195-afe-clk: Use guard() for spin locks
https://git.kernel.org/broonie/sound/c/a9f8d09ab109
[07/10] ASoC: mediatek: mt8195: mt8195-dai-etdm: Use guard() for spin locks
https://git.kernel.org/broonie/sound/c/a57e39c7ff03
[08/10] ASoC: mediatek: mt8195: mt8365-afe-clk: Use guard() for mutex & spin locks
https://git.kernel.org/broonie/sound/c/befae7299ab4
[09/10] ASoC: mediatek: mt8195: mt8365-dai-adda: Use guard() for spin locks
https://git.kernel.org/broonie/sound/c/754c2fbf8bbc
[10/10] ASoC: mediatek: mt8195: mt8365-dai-i2s: Use guard() for spin locks
https://git.kernel.org/broonie/sound/c/62bde3771c3b
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply
* [PATCH v6 7/7] arm64: dts: mediatek: Add MediaTek MT6392 PMIC dtsi
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Louis-Alexis Eyraud,
Julien Massot, Fabien Parent, Akari Tsuyukusa, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add the dts to be included by all boards using the MT6392 PMIC,
providing support for keys, pinctrl and RTC.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 41 ++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
diff --git a/arch/arm64/boot/dts/mediatek/mt6392.dtsi b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
new file mode 100644
index 000000000000..b8d943e47816
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Copyright (c) 2024 Val Packett <val@packett.cool>
+ */
+
+#include <dt-bindings/input/input.h>
+
+&pwrap {
+ pmic: pmic {
+ compatible = "mediatek,mt6392", "mediatek,mt6323";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ mt6392keys: keys {
+ compatible = "mediatek,mt6392-keys";
+
+ key-power {
+ linux,keycodes = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ key-home {
+ linux,keycodes = <KEY_HOME>;
+ wakeup-source;
+ };
+ };
+
+ mt6392pio: pinctrl {
+ compatible = "mediatek,mt6392-pinctrl";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mt6392rtc: rtc {
+ compatible = "mediatek,mt6392-rtc",
+ "mediatek,mt6323-rtc";
+ };
+ };
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v6 6/7] pinctrl: mediatek: mt6397: Add MediaTek MT6392
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, AngeloGioacchino Del Regno,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
Linus Walleij, Louis-Alexis Eyraud, Julien Massot, Val Packett,
Fabien Parent, Akari Tsuyukusa, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
Add support for the MT6392 pinctrl device, which is very similar to
MT6397 with a handful of different property values and its own pins
definition.
Update the MT6397 driver to retrieve device data from the match table and
use it for driver init.
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/pinctrl/mediatek/pinctrl-mt6397.c | 37 ++++++++++-
drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h | 64 +++++++++++++++++++
2 files changed, 99 insertions(+), 2 deletions(-)
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6397.c b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
index 03d0f65d7bcc..8ba02e70595c 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
@@ -12,10 +12,32 @@
#include <linux/mfd/mt6397/core.h>
#include "pinctrl-mtk-common.h"
+#include "pinctrl-mtk-mt6392.h"
#include "pinctrl-mtk-mt6397.h"
#define MT6397_PIN_REG_BASE 0xc000
+static const struct mtk_pinctrl_devdata mt6392_pinctrl_data = {
+ .pins = mtk_pins_mt6392,
+ .npins = ARRAY_SIZE(mtk_pins_mt6392),
+ .dir_offset = (MT6397_PIN_REG_BASE + 0x000),
+ .ies_offset = MTK_PINCTRL_NOT_SUPPORT,
+ .smt_offset = MTK_PINCTRL_NOT_SUPPORT,
+ .pullen_offset = (MT6397_PIN_REG_BASE + 0x020),
+ .pullsel_offset = (MT6397_PIN_REG_BASE + 0x040),
+ .dout_offset = (MT6397_PIN_REG_BASE + 0x080),
+ .din_offset = (MT6397_PIN_REG_BASE + 0x0a0),
+ .pinmux_offset = (MT6397_PIN_REG_BASE + 0x0c0),
+ .type1_start = 7,
+ .type1_end = 7,
+ .port_shf = 3,
+ .port_mask = 0x3,
+ .port_align = 2,
+ .mode_mask = 0xf,
+ .mode_per_reg = 5,
+ .mode_shf = 4,
+};
+
static const struct mtk_pinctrl_devdata mt6397_pinctrl_data = {
.pins = mtk_pins_mt6397,
.npins = ARRAY_SIZE(mtk_pins_mt6397),
@@ -40,13 +62,24 @@ static const struct mtk_pinctrl_devdata mt6397_pinctrl_data = {
static int mt6397_pinctrl_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397;
+ const struct mtk_pinctrl_devdata *data;
+
+ data = device_get_match_data(&pdev->dev);
+ if (!data)
+ return -ENOENT;
mt6397 = dev_get_drvdata(pdev->dev.parent);
- return mtk_pctrl_init(pdev, &mt6397_pinctrl_data, mt6397->regmap);
+ return mtk_pctrl_init(pdev, data, mt6397->regmap);
}
static const struct of_device_id mt6397_pctrl_match[] = {
- { .compatible = "mediatek,mt6397-pinctrl", },
+ {
+ .compatible = "mediatek,mt6392-pinctrl",
+ .data = &mt6392_pinctrl_data
+ }, {
+ .compatible = "mediatek,mt6397-pinctrl",
+ .data = &mt6397_pinctrl_data
+ },
{ }
};
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
new file mode 100644
index 000000000000..e7241af28fdb
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PINCTRL_MTK_MT6392_H
+#define __PINCTRL_MTK_MT6392_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mtk-common.h"
+
+static const struct mtk_desc_pin mtk_pins_mt6392[] = {
+ MTK_PIN(PINCTRL_PIN(0, "INT"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO0"),
+ MTK_FUNCTION(1, "INT"),
+ MTK_FUNCTION(5, "TEST_CK2"),
+ MTK_FUNCTION(6, "TEST_IN1"),
+ MTK_FUNCTION(7, "TEST_OUT1")
+ ),
+ MTK_PIN(PINCTRL_PIN(1, "SRCLKEN"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO1"),
+ MTK_FUNCTION(1, "SRCLKEN"),
+ MTK_FUNCTION(5, "TEST_CK0"),
+ MTK_FUNCTION(6, "TEST_IN2"),
+ MTK_FUNCTION(7, "TEST_OUT2")
+ ),
+ MTK_PIN(PINCTRL_PIN(2, "RTC_32K1V8"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO2"),
+ MTK_FUNCTION(1, "RTC_32K1V8"),
+ MTK_FUNCTION(5, "TEST_CK1"),
+ MTK_FUNCTION(6, "TEST_IN3"),
+ MTK_FUNCTION(7, "TEST_OUT3")
+ ),
+ MTK_PIN(PINCTRL_PIN(3, "SPI_CLK"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO3"),
+ MTK_FUNCTION(1, "SPI_CLK")
+ ),
+ MTK_PIN(PINCTRL_PIN(4, "SPI_CSN"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO4"),
+ MTK_FUNCTION(1, "SPI_CSN")
+ ),
+ MTK_PIN(PINCTRL_PIN(5, "SPI_MOSI"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO5"),
+ MTK_FUNCTION(1, "SPI_MOSI")
+ ),
+ MTK_PIN(PINCTRL_PIN(6, "SPI_MISO"),
+ NULL, "mt6392",
+ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+ MTK_FUNCTION(0, "GPIO6"),
+ MTK_FUNCTION(1, "SPI_MISO"),
+ MTK_FUNCTION(6, "TEST_IN4"),
+ MTK_FUNCTION(7, "TEST_OUT4")
+ ),
+};
+
+#endif /* __PINCTRL_MTK_MT6392_H */
--
2.43.0
^ permalink raw reply related
* [PATCH v6 5/7] input: keyboard: mtk-pmic-keys: Add MT6392 support
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, AngeloGioacchino Del Regno,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
Linus Walleij, Julien Massot, Louis-Alexis Eyraud, Fabien Parent,
Akari Tsuyukusa, Chen Zhong, linux-input, devicetree,
linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add support for the MT6392 PMIC to the keys driver.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/keyboard/mtk-pmic-keys.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index c78d9f6d97c4..8b4a89fce4fb 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -13,6 +13,7 @@
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6359/registers.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
#include <linux/module.h>
@@ -69,6 +70,19 @@ static const struct mtk_pmic_regs mt6397_regs = {
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
};
+static const struct mtk_pmic_regs mt6392_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS, 0x2,
+ MT6392_INT_MISC_CON, 0x10,
+ MTK_PMIC_PWRKEY_RST),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS, 0x4,
+ MT6392_INT_MISC_CON, 0x8,
+ MTK_PMIC_HOMEKEY_RST),
+ .pmic_rst_reg = MT6392_TOP_RST_MISC,
+ .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
+};
+
static const struct mtk_pmic_regs mt6323_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
@@ -301,6 +315,9 @@ static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
{
.compatible = "mediatek,mt6397-keys",
.data = &mt6397_regs,
+ }, {
+ .compatible = "mediatek,mt6392-keys",
+ .data = &mt6392_regs,
}, {
.compatible = "mediatek,mt6323-keys",
.data = &mt6323_regs,
--
2.43.0
^ permalink raw reply related
* [PATCH v6 4/7] mfd: mt6397: Add support for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
AngeloGioacchino Del Regno, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger, Linus Walleij,
Louis-Alexis Eyraud, Julien Massot, Akari Tsuyukusa, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Align the MT6397 PMIC driver to other MFD drivers by passing only an
identifier through mt6397_of_match[*].data and add support for the MT6392
PMIC and its RTC, keys and pinctrl devices.
The keys device manages two key IRQs named PWRKEY and FCHR_ENB in the data
sheet, but it does not explain what the last acronym means exactly.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/mfd/mt6397-core.c | 97 ++++--
drivers/mfd/mt6397-irq.c | 8 +
include/linux/mfd/mt6392/core.h | 43 +++
include/linux/mfd/mt6392/registers.h | 488 +++++++++++++++++++++++++++
include/linux/mfd/mt6397/core.h | 1 +
5 files changed, 611 insertions(+), 26 deletions(-)
create mode 100644 include/linux/mfd/mt6392/core.h
create mode 100644 include/linux/mfd/mt6392/registers.h
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index ccd97d66d7f1..8234210f148e 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -18,6 +18,7 @@
#include <linux/mfd/mt6357/core.h>
#include <linux/mfd/mt6358/core.h>
#include <linux/mfd/mt6359/core.h>
+#include <linux/mfd/mt6392/core.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
#include <linux/mfd/mt6328/registers.h>
@@ -25,6 +26,7 @@
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6359/registers.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/registers.h>
#define MT6323_RTC_BASE 0x8000
@@ -39,6 +41,9 @@
#define MT6358_RTC_BASE 0x0588
#define MT6358_RTC_SIZE 0x3c
+#define MT6392_RTC_BASE 0x8000
+#define MT6392_RTC_SIZE 0x3e
+
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
@@ -65,6 +70,11 @@ static const struct resource mt6358_rtc_resources[] = {
DEFINE_RES_IRQ(MT6358_IRQ_RTC),
};
+static const struct resource mt6392_rtc_resources[] = {
+ DEFINE_RES_MEM(MT6392_RTC_BASE, MT6392_RTC_SIZE),
+ DEFINE_RES_IRQ(MT6392_IRQ_RTC),
+};
+
static const struct resource mt6397_rtc_resources[] = {
DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
DEFINE_RES_IRQ(MT6397_IRQ_RTC),
@@ -114,6 +124,11 @@ static const struct resource mt6331_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
};
+static const struct resource mt6392_keys_resources[] = {
+ DEFINE_RES_IRQ_NAMED(MT6392_IRQ_PWRKEY, "powerkey"),
+ DEFINE_RES_IRQ_NAMED(MT6392_IRQ_FCHRKEY, "homekey"),
+};
+
static const struct resource mt6397_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
@@ -193,6 +208,15 @@ static const struct mfd_cell mt6359_devs[] = {
"mediatek,mt6359-accdet"),
};
+static const struct mfd_cell mt6392_devs[] = {
+ MFD_CELL_OF("mt6392-keys", mt6392_keys_resources, NULL, 0, 0,
+ "mediatek,mt6392-keys"),
+ MFD_CELL_OF("mt6392-pinctrl", NULL, NULL, 0, 0,
+ "mediatek,mt6392-pinctrl"),
+ MFD_CELL_OF("mt6392-rtc", mt6392_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6392-rtc"),
+};
+
static const struct mfd_cell mt6397_devs[] = {
MFD_CELL_OF("mt6397-rtc", mt6397_rtc_resources, NULL, 0, 0,
"mediatek,mt6397-rtc"),
@@ -264,6 +288,14 @@ static const struct chip_data mt6359_core = {
.irq_init = mt6358_irq_init,
};
+static const struct chip_data mt6392_core = {
+ .cid_addr = MT6392_CID,
+ .cid_shift = 0,
+ .cells = mt6392_devs,
+ .cell_size = ARRAY_SIZE(mt6392_devs),
+ .irq_init = mt6397_irq_init,
+};
+
static const struct chip_data mt6397_core = {
.cid_addr = MT6397_CID,
.cid_shift = 0,
@@ -278,6 +310,7 @@ static int mt6397_probe(struct platform_device *pdev)
unsigned int id = 0;
struct mt6397_chip *pmic;
const struct chip_data *pmic_core;
+ int chip_variant;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
@@ -293,9 +326,36 @@ static int mt6397_probe(struct platform_device *pdev)
if (!pmic->regmap)
return -ENODEV;
- pmic_core = of_device_get_match_data(&pdev->dev);
- if (!pmic_core)
+ chip_variant = (unsigned int)(uintptr_t)device_get_match_data(&pdev->dev);
+ switch (chip_variant) {
+ case MT6323_CHIP_ID:
+ pmic_core = &mt6323_core;
+ break;
+ case MT6328_CHIP_ID:
+ pmic_core = &mt6328_core;
+ break;
+ case MT6331_CHIP_ID:
+ pmic_core = &mt6331_mt6332_core;
+ break;
+ case MT6357_CHIP_ID:
+ pmic_core = &mt6357_core;
+ break;
+ case MT6358_CHIP_ID:
+ pmic_core = &mt6358_core;
+ break;
+ case MT6359_CHIP_ID:
+ pmic_core = &mt6359_core;
+ break;
+ case MT6392_CHIP_ID:
+ pmic_core = &mt6392_core;
+ break;
+ case MT6397_CHIP_ID:
+ pmic_core = &mt6397_core;
+ break;
+ default:
+ dev_err(&pdev->dev, "Device not supported\n");
return -ENODEV;
+ }
ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
if (ret) {
@@ -327,30 +387,15 @@ static int mt6397_probe(struct platform_device *pdev)
}
static const struct of_device_id mt6397_of_match[] = {
- {
- .compatible = "mediatek,mt6323",
- .data = &mt6323_core,
- }, {
- .compatible = "mediatek,mt6328",
- .data = &mt6328_core,
- }, {
- .compatible = "mediatek,mt6331",
- .data = &mt6331_mt6332_core,
- }, {
- .compatible = "mediatek,mt6357",
- .data = &mt6357_core,
- }, {
- .compatible = "mediatek,mt6358",
- .data = &mt6358_core,
- }, {
- .compatible = "mediatek,mt6359",
- .data = &mt6359_core,
- }, {
- .compatible = "mediatek,mt6397",
- .data = &mt6397_core,
- }, {
- /* sentinel */
- }
+ { .compatible = "mediatek,mt6323", .data = (void *)MT6323_CHIP_ID, },
+ { .compatible = "mediatek,mt6328", .data = (void *)MT6328_CHIP_ID, },
+ { .compatible = "mediatek,mt6331", .data = (void *)MT6331_CHIP_ID, },
+ { .compatible = "mediatek,mt6357", .data = (void *)MT6357_CHIP_ID, },
+ { .compatible = "mediatek,mt6358", .data = (void *)MT6358_CHIP_ID, },
+ { .compatible = "mediatek,mt6359", .data = (void *)MT6359_CHIP_ID, },
+ { .compatible = "mediatek,mt6392", .data = (void *)MT6392_CHIP_ID, },
+ { .compatible = "mediatek,mt6397", .data = (void *)MT6397_CHIP_ID, },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mt6397_of_match);
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 5d2e5459f744..80ea5b92d232 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -15,6 +15,8 @@
#include <linux/mfd/mt6328/registers.h>
#include <linux/mfd/mt6331/core.h>
#include <linux/mfd/mt6331/registers.h>
+#include <linux/mfd/mt6392/core.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
@@ -203,6 +205,12 @@ int mt6397_irq_init(struct mt6397_chip *chip)
chip->int_status[0] = MT6397_INT_STATUS0;
chip->int_status[1] = MT6397_INT_STATUS1;
break;
+ case MT6392_CHIP_ID:
+ chip->int_con[0] = MT6392_INT_CON0;
+ chip->int_con[1] = MT6392_INT_CON1;
+ chip->int_status[0] = MT6392_INT_STATUS0;
+ chip->int_status[1] = MT6392_INT_STATUS1;
+ break;
default:
dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
diff --git a/include/linux/mfd/mt6392/core.h b/include/linux/mfd/mt6392/core.h
new file mode 100644
index 000000000000..8777b3abf929
--- /dev/null
+++ b/include/linux/mfd/mt6392/core.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Copyright (c) 2026 Luca Leonardo Scorcia <l.scorcia@gmail.com>
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __MFD_MT6392_CORE_H__
+#define __MFD_MT6392_CORE_H__
+
+enum mt6392_irq_numbers {
+ MT6392_IRQ_SPKL_AB = 0,
+ MT6392_IRQ_SPKL,
+ MT6392_IRQ_BAT_L,
+ MT6392_IRQ_BAT_H,
+ MT6392_IRQ_WATCHDOG,
+ MT6392_IRQ_PWRKEY,
+ MT6392_IRQ_THR_L,
+ MT6392_IRQ_THR_H,
+ MT6392_IRQ_VBATON_UNDET,
+ MT6392_IRQ_BVALID_DET,
+ MT6392_IRQ_CHRDET,
+ MT6392_IRQ_OV,
+ MT6392_IRQ_LDO = 16,
+ MT6392_IRQ_FCHRKEY,
+ MT6392_IRQ_RELEASE_PWRKEY,
+ MT6392_IRQ_RELEASE_FCHRKEY,
+ MT6392_IRQ_RTC,
+ MT6392_IRQ_VPROC,
+ MT6392_IRQ_VSYS,
+ MT6392_IRQ_VCORE,
+ MT6392_IRQ_TYPE_C_CC,
+ MT6392_IRQ_TYPEC_H_MAX,
+ MT6392_IRQ_TYPEC_H_MIN,
+ MT6392_IRQ_TYPEC_L_MAX,
+ MT6392_IRQ_TYPEC_L_MIN,
+ MT6392_IRQ_THR_MAX,
+ MT6392_IRQ_THR_MIN,
+ MT6392_IRQ_NAG_C_DLTV,
+ MT6392_IRQ_NR,
+};
+
+#endif /* __MFD_MT6392_CORE_H__ */
diff --git a/include/linux/mfd/mt6392/registers.h b/include/linux/mfd/mt6392/registers.h
new file mode 100644
index 000000000000..68fe9af448f5
--- /dev/null
+++ b/include/linux/mfd/mt6392/registers.h
@@ -0,0 +1,488 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Copyright (c) 2026 Luca Leonardo Scorcia <l.scorcia@gmail.com>
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __MFD_MT6392_REGISTERS_H__
+#define __MFD_MT6392_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6392_CHR_CON0 0x0000
+#define MT6392_CHR_CON1 0x0002
+#define MT6392_CHR_CON2 0x0004
+#define MT6392_CHR_CON3 0x0006
+#define MT6392_CHR_CON4 0x0008
+#define MT6392_CHR_CON5 0x000A
+#define MT6392_CHR_CON6 0x000C
+#define MT6392_CHR_CON7 0x000E
+#define MT6392_CHR_CON8 0x0010
+#define MT6392_CHR_CON9 0x0012
+#define MT6392_CHR_CON10 0x0014
+#define MT6392_CHR_CON11 0x0016
+#define MT6392_CHR_CON12 0x0018
+#define MT6392_CHR_CON13 0x001A
+#define MT6392_CHR_CON14 0x001C
+#define MT6392_CHR_CON15 0x001E
+#define MT6392_CHR_CON16 0x0020
+#define MT6392_CHR_CON17 0x0022
+#define MT6392_CHR_CON18 0x0024
+#define MT6392_CHR_CON19 0x0026
+#define MT6392_CHR_CON20 0x0028
+#define MT6392_CHR_CON21 0x002A
+#define MT6392_CHR_CON22 0x002C
+#define MT6392_CHR_CON23 0x002E
+#define MT6392_CHR_CON24 0x0030
+#define MT6392_CHR_CON25 0x0032
+#define MT6392_CHR_CON26 0x0034
+#define MT6392_CHR_CON27 0x0036
+#define MT6392_CHR_CON28 0x0038
+#define MT6392_CHR_CON29 0x003A
+#define MT6392_STRUP_CON0 0x003C
+#define MT6392_STRUP_CON2 0x003E
+#define MT6392_STRUP_CON3 0x0040
+#define MT6392_STRUP_CON4 0x0042
+#define MT6392_STRUP_CON5 0x0044
+#define MT6392_STRUP_CON6 0x0046
+#define MT6392_STRUP_CON7 0x0048
+#define MT6392_STRUP_CON8 0x004A
+#define MT6392_STRUP_CON9 0x004C
+#define MT6392_STRUP_CON10 0x004E
+#define MT6392_STRUP_CON11 0x0050
+#define MT6392_SPK_CON0 0x0052
+#define MT6392_SPK_CON1 0x0054
+#define MT6392_SPK_CON2 0x0056
+#define MT6392_SPK_CON6 0x005E
+#define MT6392_SPK_CON7 0x0060
+#define MT6392_SPK_CON8 0x0062
+#define MT6392_SPK_CON9 0x0064
+#define MT6392_SPK_CON10 0x0066
+#define MT6392_SPK_CON11 0x0068
+#define MT6392_SPK_CON12 0x006A
+#define MT6392_STRUP_CON12 0x006E
+#define MT6392_STRUP_CON13 0x0070
+#define MT6392_STRUP_CON14 0x0072
+#define MT6392_STRUP_CON15 0x0074
+#define MT6392_STRUP_CON16 0x0076
+#define MT6392_STRUP_CON17 0x0078
+#define MT6392_STRUP_CON18 0x007A
+#define MT6392_STRUP_CON19 0x007C
+#define MT6392_STRUP_CON20 0x007E
+#define MT6392_CID 0x0100
+#define MT6392_TOP_CKPDN0 0x0102
+#define MT6392_TOP_CKPDN0_SET 0x0104
+#define MT6392_TOP_CKPDN0_CLR 0x0106
+#define MT6392_TOP_CKPDN1 0x0108
+#define MT6392_TOP_CKPDN1_SET 0x010A
+#define MT6392_TOP_CKPDN1_CLR 0x010C
+#define MT6392_TOP_CKPDN2 0x010E
+#define MT6392_TOP_CKPDN2_SET 0x0110
+#define MT6392_TOP_CKPDN2_CLR 0x0112
+#define MT6392_TOP_RST_CON 0x0114
+#define MT6392_TOP_RST_CON_SET 0x0116
+#define MT6392_TOP_RST_CON_CLR 0x0118
+#define MT6392_TOP_RST_MISC 0x011A
+#define MT6392_TOP_RST_MISC_SET 0x011C
+#define MT6392_TOP_RST_MISC_CLR 0x011E
+#define MT6392_TOP_CKCON0 0x0120
+#define MT6392_TOP_CKCON0_SET 0x0122
+#define MT6392_TOP_CKCON0_CLR 0x0124
+#define MT6392_TOP_CKCON1 0x0126
+#define MT6392_TOP_CKCON1_SET 0x0128
+#define MT6392_TOP_CKCON1_CLR 0x012A
+#define MT6392_TOP_CKTST0 0x012C
+#define MT6392_TOP_CKTST1 0x012E
+#define MT6392_TOP_CKTST2 0x0130
+#define MT6392_TEST_OUT 0x0132
+#define MT6392_TEST_CON0 0x0134
+#define MT6392_TEST_CON1 0x0136
+#define MT6392_EN_STATUS0 0x0138
+#define MT6392_EN_STATUS1 0x013A
+#define MT6392_OCSTATUS0 0x013C
+#define MT6392_OCSTATUS1 0x013E
+#define MT6392_PGSTATUS 0x0140
+#define MT6392_CHRSTATUS 0x0142
+#define MT6392_TDSEL_CON 0x0144
+#define MT6392_RDSEL_CON 0x0146
+#define MT6392_SMT_CON0 0x0148
+#define MT6392_SMT_CON1 0x014A
+#define MT6392_DRV_CON0 0x0152
+#define MT6392_DRV_CON1 0x0154
+#define MT6392_INT_CON0 0x0160
+#define MT6392_INT_CON0_SET 0x0162
+#define MT6392_INT_CON0_CLR 0x0164
+#define MT6392_INT_CON1 0x0166
+#define MT6392_INT_CON1_SET 0x0168
+#define MT6392_INT_CON1_CLR 0x016A
+#define MT6392_INT_MISC_CON 0x016C
+#define MT6392_INT_MISC_CON_SET 0x016E
+#define MT6392_INT_MISC_CON_CLR 0x0170
+#define MT6392_INT_STATUS0 0x0172
+#define MT6392_INT_STATUS1 0x0174
+#define MT6392_OC_GEAR_0 0x0176
+#define MT6392_OC_GEAR_1 0x0178
+#define MT6392_OC_GEAR_2 0x017A
+#define MT6392_OC_CTL_VPROC 0x017C
+#define MT6392_OC_CTL_VSYS 0x017E
+#define MT6392_OC_CTL_VCORE 0x0180
+#define MT6392_FQMTR_CON0 0x0182
+#define MT6392_FQMTR_CON1 0x0184
+#define MT6392_FQMTR_CON2 0x0186
+#define MT6392_RG_SPI_CON 0x0188
+#define MT6392_DEW_DIO_EN 0x018A
+#define MT6392_DEW_READ_TEST 0x018C
+#define MT6392_DEW_WRITE_TEST 0x018E
+#define MT6392_DEW_CRC_SWRST 0x0190
+#define MT6392_DEW_CRC_EN 0x0192
+#define MT6392_DEW_CRC_VAL 0x0194
+#define MT6392_DEW_DBG_MON_SEL 0x0196
+#define MT6392_DEW_CIPHER_KEY_SEL 0x0198
+#define MT6392_DEW_CIPHER_IV_SEL 0x019A
+#define MT6392_DEW_CIPHER_EN 0x019C
+#define MT6392_DEW_CIPHER_RDY 0x019E
+#define MT6392_DEW_CIPHER_MODE 0x01A0
+#define MT6392_DEW_CIPHER_SWRST 0x01A2
+#define MT6392_DEW_RDDMY_NO 0x01A4
+#define MT6392_DEW_RDATA_DLY_SEL 0x01A6
+#define MT6392_CLK_TRIM_CON0 0x01A8
+#define MT6392_BUCK_CON0 0x0200
+#define MT6392_BUCK_CON1 0x0202
+#define MT6392_BUCK_CON2 0x0204
+#define MT6392_BUCK_CON3 0x0206
+#define MT6392_BUCK_CON4 0x0208
+#define MT6392_BUCK_CON5 0x020A
+#define MT6392_VPROC_CON0 0x020C
+#define MT6392_VPROC_CON1 0x020E
+#define MT6392_VPROC_CON2 0x0210
+#define MT6392_VPROC_CON3 0x0212
+#define MT6392_VPROC_CON4 0x0214
+#define MT6392_VPROC_CON5 0x0216
+#define MT6392_VPROC_CON7 0x021A
+#define MT6392_VPROC_CON8 0x021C
+#define MT6392_VPROC_CON9 0x021E
+#define MT6392_VPROC_CON10 0x0220
+#define MT6392_VPROC_CON11 0x0222
+#define MT6392_VPROC_CON12 0x0224
+#define MT6392_VPROC_CON13 0x0226
+#define MT6392_VPROC_CON14 0x0228
+#define MT6392_VPROC_CON15 0x022A
+#define MT6392_VPROC_CON18 0x0230
+#define MT6392_VSYS_CON0 0x0232
+#define MT6392_VSYS_CON1 0x0234
+#define MT6392_VSYS_CON2 0x0236
+#define MT6392_VSYS_CON3 0x0238
+#define MT6392_VSYS_CON4 0x023A
+#define MT6392_VSYS_CON5 0x023C
+#define MT6392_VSYS_CON7 0x0240
+#define MT6392_VSYS_CON8 0x0242
+#define MT6392_VSYS_CON9 0x0244
+#define MT6392_VSYS_CON10 0x0246
+#define MT6392_VSYS_CON11 0x0248
+#define MT6392_VSYS_CON12 0x024A
+#define MT6392_VSYS_CON13 0x024C
+#define MT6392_VSYS_CON14 0x024E
+#define MT6392_VSYS_CON15 0x0250
+#define MT6392_VSYS_CON18 0x0256
+#define MT6392_BUCK_OC_CON0 0x0258
+#define MT6392_BUCK_OC_CON1 0x025A
+#define MT6392_BUCK_OC_CON2 0x025C
+#define MT6392_BUCK_OC_CON3 0x025E
+#define MT6392_BUCK_OC_CON4 0x0260
+#define MT6392_BUCK_OC_VPROC_CON0 0x0262
+#define MT6392_BUCK_OC_VCORE_CON0 0x0264
+#define MT6392_BUCK_OC_VSYS_CON0 0x0266
+#define MT6392_BUCK_ANA_MON_CON0 0x0268
+#define MT6392_BUCK_EFUSE_OC_CON0 0x026A
+#define MT6392_VCORE_CON0 0x0300
+#define MT6392_VCORE_CON1 0x0302
+#define MT6392_VCORE_CON2 0x0304
+#define MT6392_VCORE_CON3 0x0306
+#define MT6392_VCORE_CON4 0x0308
+#define MT6392_VCORE_CON5 0x030A
+#define MT6392_VCORE_CON7 0x030E
+#define MT6392_VCORE_CON8 0x0310
+#define MT6392_VCORE_CON9 0x0312
+#define MT6392_VCORE_CON10 0x0314
+#define MT6392_VCORE_CON11 0x0316
+#define MT6392_VCORE_CON12 0x0318
+#define MT6392_VCORE_CON13 0x031A
+#define MT6392_VCORE_CON14 0x031C
+#define MT6392_VCORE_CON15 0x031E
+#define MT6392_VCORE_CON18 0x0324
+#define MT6392_BUCK_K_CON0 0x032A
+#define MT6392_BUCK_K_CON1 0x032C
+#define MT6392_BUCK_K_CON2 0x032E
+#define MT6392_ANALDO_CON0 0x0400
+#define MT6392_ANALDO_CON1 0x0402
+#define MT6392_ANALDO_CON2 0x0404
+#define MT6392_ANALDO_CON3 0x0406
+#define MT6392_ANALDO_CON4 0x0408
+#define MT6392_ANALDO_CON6 0x040C
+#define MT6392_ANALDO_CON7 0x040E
+#define MT6392_ANALDO_CON8 0x0410
+#define MT6392_ANALDO_CON10 0x0412
+#define MT6392_ANALDO_CON15 0x0414
+#define MT6392_ANALDO_CON16 0x0416
+#define MT6392_ANALDO_CON17 0x0418
+#define MT6392_ANALDO_CON21 0x0420
+#define MT6392_ANALDO_CON22 0x0422
+#define MT6392_ANALDO_CON23 0x0424
+#define MT6392_ANALDO_CON24 0x0426
+#define MT6392_ANALDO_CON25 0x0428
+#define MT6392_ANALDO_CON26 0x042A
+#define MT6392_ANALDO_CON27 0x042C
+#define MT6392_ANALDO_CON28 0x042E
+#define MT6392_ANALDO_CON29 0x0430
+#define MT6392_DIGLDO_CON0 0x0500
+#define MT6392_DIGLDO_CON2 0x0502
+#define MT6392_DIGLDO_CON3 0x0504
+#define MT6392_DIGLDO_CON5 0x0506
+#define MT6392_DIGLDO_CON6 0x0508
+#define MT6392_DIGLDO_CON7 0x050A
+#define MT6392_DIGLDO_CON8 0x050C
+#define MT6392_DIGLDO_CON10 0x0510
+#define MT6392_DIGLDO_CON11 0x0512
+#define MT6392_DIGLDO_CON12 0x0514
+#define MT6392_DIGLDO_CON15 0x051A
+#define MT6392_DIGLDO_CON20 0x0524
+#define MT6392_DIGLDO_CON21 0x0526
+#define MT6392_DIGLDO_CON23 0x0528
+#define MT6392_DIGLDO_CON24 0x052A
+#define MT6392_DIGLDO_CON26 0x052C
+#define MT6392_DIGLDO_CON27 0x052E
+#define MT6392_DIGLDO_CON28 0x0530
+#define MT6392_DIGLDO_CON29 0x0532
+#define MT6392_DIGLDO_CON30 0x0534
+#define MT6392_DIGLDO_CON31 0x0536
+#define MT6392_DIGLDO_CON32 0x0538
+#define MT6392_DIGLDO_CON33 0x053A
+#define MT6392_DIGLDO_CON36 0x0540
+#define MT6392_DIGLDO_CON41 0x0546
+#define MT6392_DIGLDO_CON44 0x054C
+#define MT6392_DIGLDO_CON47 0x0552
+#define MT6392_DIGLDO_CON48 0x0554
+#define MT6392_DIGLDO_CON49 0x0556
+#define MT6392_DIGLDO_CON50 0x0558
+#define MT6392_DIGLDO_CON51 0x055A
+#define MT6392_DIGLDO_CON52 0x055C
+#define MT6392_DIGLDO_CON53 0x055E
+#define MT6392_DIGLDO_CON54 0x0560
+#define MT6392_DIGLDO_CON55 0x0562
+#define MT6392_DIGLDO_CON56 0x0564
+#define MT6392_DIGLDO_CON57 0x0566
+#define MT6392_DIGLDO_CON58 0x0568
+#define MT6392_DIGLDO_CON59 0x056A
+#define MT6392_DIGLDO_CON60 0x056C
+#define MT6392_DIGLDO_CON61 0x056E
+#define MT6392_DIGLDO_CON62 0x0570
+#define MT6392_DIGLDO_CON63 0x0572
+#define MT6392_EFUSE_CON0 0x0600
+#define MT6392_EFUSE_CON1 0x0602
+#define MT6392_EFUSE_CON2 0x0604
+#define MT6392_EFUSE_CON3 0x0606
+#define MT6392_EFUSE_CON4 0x0608
+#define MT6392_EFUSE_CON5 0x060A
+#define MT6392_EFUSE_CON6 0x060C
+#define MT6392_EFUSE_VAL_0_15 0x060E
+#define MT6392_EFUSE_VAL_16_31 0x0610
+#define MT6392_EFUSE_VAL_32_47 0x0612
+#define MT6392_EFUSE_VAL_48_63 0x0614
+#define MT6392_EFUSE_VAL_64_79 0x0616
+#define MT6392_EFUSE_VAL_80_95 0x0618
+#define MT6392_EFUSE_VAL_96_111 0x061A
+#define MT6392_EFUSE_VAL_112_127 0x061C
+#define MT6392_EFUSE_VAL_128_143 0x061E
+#define MT6392_EFUSE_VAL_144_159 0x0620
+#define MT6392_EFUSE_VAL_160_175 0x0622
+#define MT6392_EFUSE_VAL_176_191 0x0624
+#define MT6392_EFUSE_VAL_192_207 0x0626
+#define MT6392_EFUSE_VAL_208_223 0x0628
+#define MT6392_EFUSE_VAL_224_239 0x062A
+#define MT6392_EFUSE_VAL_240_255 0x062C
+#define MT6392_EFUSE_VAL_256_271 0x062E
+#define MT6392_EFUSE_VAL_272_287 0x0630
+#define MT6392_EFUSE_VAL_288_303 0x0632
+#define MT6392_EFUSE_VAL_304_319 0x0634
+#define MT6392_EFUSE_VAL_320_335 0x0636
+#define MT6392_EFUSE_VAL_336_351 0x0638
+#define MT6392_EFUSE_VAL_352_367 0x063A
+#define MT6392_EFUSE_VAL_368_383 0x063C
+#define MT6392_EFUSE_VAL_384_399 0x063E
+#define MT6392_EFUSE_VAL_400_415 0x0640
+#define MT6392_EFUSE_VAL_416_431 0x0642
+#define MT6392_RTC_MIX_CON0 0x0644
+#define MT6392_RTC_MIX_CON1 0x0646
+#define MT6392_EFUSE_VAL_432_447 0x0648
+#define MT6392_EFUSE_VAL_448_463 0x064A
+#define MT6392_EFUSE_VAL_464_479 0x064C
+#define MT6392_EFUSE_VAL_480_495 0x064E
+#define MT6392_EFUSE_VAL_496_511 0x0650
+#define MT6392_EFUSE_DOUT_0_15 0x0652
+#define MT6392_EFUSE_DOUT_16_31 0x0654
+#define MT6392_EFUSE_DOUT_32_47 0x0656
+#define MT6392_EFUSE_DOUT_48_63 0x0658
+#define MT6392_EFUSE_DOUT_64_79 0x065A
+#define MT6392_EFUSE_DOUT_80_95 0x065C
+#define MT6392_EFUSE_DOUT_96_111 0x065E
+#define MT6392_EFUSE_DOUT_112_127 0x0660
+#define MT6392_EFUSE_DOUT_128_143 0x0662
+#define MT6392_EFUSE_DOUT_144_159 0x0664
+#define MT6392_EFUSE_DOUT_160_175 0x0666
+#define MT6392_EFUSE_DOUT_176_191 0x0668
+#define MT6392_EFUSE_DOUT_192_207 0x066A
+#define MT6392_EFUSE_DOUT_208_223 0x066C
+#define MT6392_EFUSE_DOUT_224_239 0x066E
+#define MT6392_EFUSE_DOUT_240_255 0x0670
+#define MT6392_EFUSE_DOUT_256_271 0x0672
+#define MT6392_EFUSE_DOUT_272_287 0x0674
+#define MT6392_EFUSE_DOUT_288_303 0x0676
+#define MT6392_EFUSE_DOUT_304_319 0x0678
+#define MT6392_EFUSE_DOUT_320_335 0x067A
+#define MT6392_EFUSE_DOUT_336_351 0x067C
+#define MT6392_EFUSE_DOUT_352_367 0x067E
+#define MT6392_EFUSE_DOUT_368_383 0x0680
+#define MT6392_EFUSE_DOUT_384_399 0x0682
+#define MT6392_EFUSE_DOUT_400_415 0x0684
+#define MT6392_EFUSE_DOUT_416_431 0x0686
+#define MT6392_EFUSE_DOUT_432_447 0x0688
+#define MT6392_EFUSE_DOUT_448_463 0x068A
+#define MT6392_EFUSE_DOUT_464_479 0x068C
+#define MT6392_EFUSE_DOUT_480_495 0x068E
+#define MT6392_EFUSE_DOUT_496_511 0x0690
+#define MT6392_EFUSE_CON7 0x0692
+#define MT6392_EFUSE_CON8 0x0694
+#define MT6392_EFUSE_CON9 0x0696
+#define MT6392_AUXADC_ADC0 0x0700
+#define MT6392_AUXADC_ADC1 0x0702
+#define MT6392_AUXADC_ADC2 0x0704
+#define MT6392_AUXADC_ADC3 0x0706
+#define MT6392_AUXADC_ADC4 0x0708
+#define MT6392_AUXADC_ADC5 0x070A
+#define MT6392_AUXADC_ADC6 0x070C
+#define MT6392_AUXADC_ADC7 0x070E
+#define MT6392_AUXADC_ADC8 0x0710
+#define MT6392_AUXADC_ADC9 0x0712
+#define MT6392_AUXADC_ADC10 0x0714
+#define MT6392_AUXADC_ADC11 0x0716
+#define MT6392_AUXADC_ADC12 0x0718
+#define MT6392_AUXADC_ADC13 0x071A
+#define MT6392_AUXADC_ADC14 0x071C
+#define MT6392_AUXADC_ADC15 0x071E
+#define MT6392_AUXADC_ADC16 0x0720
+#define MT6392_AUXADC_ADC17 0x0722
+#define MT6392_AUXADC_ADC18 0x0724
+#define MT6392_AUXADC_ADC19 0x0726
+#define MT6392_AUXADC_ADC20 0x0728
+#define MT6392_AUXADC_ADC21 0x072A
+#define MT6392_AUXADC_ADC22 0x072C
+#define MT6392_AUXADC_STA0 0x072E
+#define MT6392_AUXADC_STA1 0x0730
+#define MT6392_AUXADC_RQST0 0x0732
+#define MT6392_AUXADC_RQST0_SET 0x0734
+#define MT6392_AUXADC_RQST0_CLR 0x0736
+#define MT6392_AUXADC_CON0 0x0738
+#define MT6392_AUXADC_CON0_SET 0x073A
+#define MT6392_AUXADC_CON0_CLR 0x073C
+#define MT6392_AUXADC_CON1 0x073E
+#define MT6392_AUXADC_CON2 0x0740
+#define MT6392_AUXADC_CON3 0x0742
+#define MT6392_AUXADC_CON4 0x0744
+#define MT6392_AUXADC_CON5 0x0746
+#define MT6392_AUXADC_CON6 0x0748
+#define MT6392_AUXADC_CON7 0x074A
+#define MT6392_AUXADC_CON8 0x074C
+#define MT6392_AUXADC_CON9 0x074E
+#define MT6392_AUXADC_CON10 0x0750
+#define MT6392_AUXADC_CON11 0x0752
+#define MT6392_AUXADC_CON12 0x0754
+#define MT6392_AUXADC_CON13 0x0756
+#define MT6392_AUXADC_CON14 0x0758
+#define MT6392_AUXADC_CON15 0x075A
+#define MT6392_AUXADC_CON16 0x075C
+#define MT6392_AUXADC_AUTORPT0 0x075E
+#define MT6392_AUXADC_LBAT0 0x0760
+#define MT6392_AUXADC_LBAT1 0x0762
+#define MT6392_AUXADC_LBAT2 0x0764
+#define MT6392_AUXADC_LBAT3 0x0766
+#define MT6392_AUXADC_LBAT4 0x0768
+#define MT6392_AUXADC_LBAT5 0x076A
+#define MT6392_AUXADC_LBAT6 0x076C
+#define MT6392_AUXADC_THR0 0x076E
+#define MT6392_AUXADC_THR1 0x0770
+#define MT6392_AUXADC_THR2 0x0772
+#define MT6392_AUXADC_THR3 0x0774
+#define MT6392_AUXADC_THR4 0x0776
+#define MT6392_AUXADC_THR5 0x0778
+#define MT6392_AUXADC_THR6 0x077A
+#define MT6392_AUXADC_EFUSE0 0x077C
+#define MT6392_AUXADC_EFUSE1 0x077E
+#define MT6392_AUXADC_EFUSE2 0x0780
+#define MT6392_AUXADC_EFUSE3 0x0782
+#define MT6392_AUXADC_EFUSE4 0x0784
+#define MT6392_AUXADC_EFUSE5 0x0786
+#define MT6392_AUXADC_NAG_0 0x0788
+#define MT6392_AUXADC_NAG_1 0x078A
+#define MT6392_AUXADC_NAG_2 0x078C
+#define MT6392_AUXADC_NAG_3 0x078E
+#define MT6392_AUXADC_NAG_4 0x0790
+#define MT6392_AUXADC_NAG_5 0x0792
+#define MT6392_AUXADC_NAG_6 0x0794
+#define MT6392_AUXADC_NAG_7 0x0796
+#define MT6392_AUXADC_NAG_8 0x0798
+#define MT6392_AUXADC_TYPEC_H_1 0x079A
+#define MT6392_AUXADC_TYPEC_H_2 0x079C
+#define MT6392_AUXADC_TYPEC_H_3 0x079E
+#define MT6392_AUXADC_TYPEC_H_4 0x07A0
+#define MT6392_AUXADC_TYPEC_H_5 0x07A2
+#define MT6392_AUXADC_TYPEC_H_6 0x07A4
+#define MT6392_AUXADC_TYPEC_H_7 0x07A6
+#define MT6392_AUXADC_TYPEC_L_1 0x07A8
+#define MT6392_AUXADC_TYPEC_L_2 0x07AA
+#define MT6392_AUXADC_TYPEC_L_3 0x07AC
+#define MT6392_AUXADC_TYPEC_L_4 0x07AE
+#define MT6392_AUXADC_TYPEC_L_5 0x07B0
+#define MT6392_AUXADC_TYPEC_L_6 0x07B2
+#define MT6392_AUXADC_TYPEC_L_7 0x07B4
+#define MT6392_AUXADC_NAG_9 0x07B6
+#define MT6392_TYPE_C_PHY_RG_0 0x0800
+#define MT6392_TYPE_C_PHY_RG_CC_RESERVE_CSR 0x0802
+#define MT6392_TYPE_C_VCMP_CTRL 0x0804
+#define MT6392_TYPE_C_CTRL 0x0806
+#define MT6392_TYPE_C_CC_SW_CTRL 0x080a
+#define MT6392_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL 0x080c
+#define MT6392_TYPE_C_CC_VOL_DEBOUNCE_CNT_VAL 0x080e
+#define MT6392_TYPE_C_DRP_SRC_CNT_VAL_0 0x0810
+#define MT6392_TYPE_C_DRP_SNK_CNT_VAL_0 0x0814
+#define MT6392_TYPE_C_DRP_TRY_CNT_VAL_0 0x0818
+#define MT6392_TYPE_C_CC_SRC_DEFAULT_DAC_VAL 0x0820
+#define MT6392_TYPE_C_CC_SRC_15_DAC_VAL 0x0822
+#define MT6392_TYPE_C_CC_SRC_30_DAC_VAL 0x0824
+#define MT6392_TYPE_C_CC_SNK_DAC_VAL_0 0x0828
+#define MT6392_TYPE_C_CC_SNK_DAC_VAL_1 0x082a
+#define MT6392_TYPE_C_INTR_EN_0 0x0830
+#define MT6392_TYPE_C_INTR_EN_2 0x0834
+#define MT6392_TYPE_C_INTR_0 0x0838
+#define MT6392_TYPE_C_INTR_2 0x083C
+#define MT6392_TYPE_C_CC_STATUS 0x0840
+#define MT6392_TYPE_C_PWR_STATUS 0x0842
+#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_0 0x0844
+#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_1 0x0846
+#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_0 0x0848
+#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_1 0x084a
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_0 0x0860
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0 0x0864
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_1 0x0866
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_1 0x0868
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_2 0x086c
+#define MT6392_TYPE_C_CC_DAC_CALI_CTRL 0x0870
+#define MT6392_TYPE_C_CC_DAC_CALI_RESULT 0x0872
+#define MT6392_TYPE_C_DEBUG_PORT_SELECT_0 0x0880
+#define MT6392_TYPE_C_DEBUG_PORT_SELECT_1 0x0882
+#define MT6392_TYPE_C_DEBUG_MODE_SELECT 0x0884
+#define MT6392_TYPE_C_DEBUG_OUT_READ_0 0x0888
+#define MT6392_TYPE_C_DEBUG_OUT_READ_1 0x088a
+#define MT6392_TYPE_C_SW_DEBUG_PORT_0 0x088c
+#define MT6392_TYPE_C_SW_DEBUG_PORT_1 0x088e
+
+#endif /* __MFD_MT6392_REGISTERS_H__ */
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index 340fc72e22aa..3729a6856c13 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -20,6 +20,7 @@ enum chip_id {
MT6359_CHIP_ID = 0x59,
MT6366_CHIP_ID = 0x66,
MT6391_CHIP_ID = 0x91,
+ MT6392_CHIP_ID = 0x92,
MT6397_CHIP_ID = 0x97,
};
--
2.43.0
^ permalink raw reply related
* [PATCH v6 3/7] mfd: mt6397: Use MFD_CELL_* to describe sub-devices
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Louis-Alexis Eyraud,
Julien Massot, Val Packett, Fabien Parent, Akari Tsuyukusa,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
Use the MFD_CELL_* macros to describe sub-devices. No functional changes.
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/mfd/mt6397-core.c | 197 ++++++++++++--------------------------
1 file changed, 63 insertions(+), 134 deletions(-)
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 1bdacda9a933..ccd97d66d7f1 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -124,159 +124,88 @@ static const struct resource mt6323_pwrc_resources[] = {
};
static const struct mfd_cell mt6323_devs[] = {
- {
- .name = "mt6323-rtc",
- .num_resources = ARRAY_SIZE(mt6323_rtc_resources),
- .resources = mt6323_rtc_resources,
- .of_compatible = "mediatek,mt6323-rtc",
- }, {
- .name = "mt6323-regulator",
- .of_compatible = "mediatek,mt6323-regulator"
- }, {
- .name = "mt6323-led",
- .of_compatible = "mediatek,mt6323-led"
- }, {
- .name = "mt6323-keys",
- .num_resources = ARRAY_SIZE(mt6323_keys_resources),
- .resources = mt6323_keys_resources,
- .of_compatible = "mediatek,mt6323-keys"
- }, {
- .name = "mt6323-pwrc",
- .num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
- .resources = mt6323_pwrc_resources,
- .of_compatible = "mediatek,mt6323-pwrc"
- },
+ MFD_CELL_OF("mt6323-rtc", mt6323_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6323-rtc"),
+ MFD_CELL_OF("mt6323-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6323-regulator"),
+ MFD_CELL_OF("mt6323-led", NULL, NULL, 0, 0,
+ "mediatek,mt6323-led"),
+ MFD_CELL_OF("mt6323-keys", mt6323_keys_resources, NULL, 0, 0,
+ "mediatek,mt6323-keys"),
+ MFD_CELL_OF("mt6323-pwrc", mt6323_pwrc_resources, NULL, 0, 0,
+ "mediatek,mt6323-pwrc"),
};
static const struct mfd_cell mt6328_devs[] = {
- {
- .name = "mt6328-regulator",
- .of_compatible = "mediatek,mt6328-regulator"
- }, {
- .name = "mt6328-keys",
- .num_resources = ARRAY_SIZE(mt6328_keys_resources),
- .resources = mt6328_keys_resources,
- .of_compatible = "mediatek,mt6328-keys"
- },
+ MFD_CELL_OF("mt6328-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6328-regulator"),
+ MFD_CELL_OF("mt6328-keys", mt6328_keys_resources, NULL, 0, 0,
+ "mediatek,mt6328-keys"),
};
static const struct mfd_cell mt6357_devs[] = {
- {
- .name = "mt6359-auxadc",
- .of_compatible = "mediatek,mt6357-auxadc"
- }, {
- .name = "mt6357-regulator",
- }, {
- .name = "mt6357-rtc",
- .num_resources = ARRAY_SIZE(mt6357_rtc_resources),
- .resources = mt6357_rtc_resources,
- .of_compatible = "mediatek,mt6357-rtc",
- }, {
- .name = "mt6357-sound",
- .of_compatible = "mediatek,mt6357-sound"
- }, {
- .name = "mt6357-keys",
- .num_resources = ARRAY_SIZE(mt6357_keys_resources),
- .resources = mt6357_keys_resources,
- .of_compatible = "mediatek,mt6357-keys"
- },
+ MFD_CELL_OF("mt6359-auxadc", NULL, NULL, 0, 0,
+ "mediatek,mt6357-auxadc"),
+ MFD_CELL_NAME("mt6357-regulator"),
+ MFD_CELL_OF("mt6357-rtc", mt6357_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6357-rtc"),
+ MFD_CELL_OF("mt6357-sound", NULL, NULL, 0, 0,
+ "mediatek,mt6357-sound"),
+ MFD_CELL_OF("mt6357-keys", mt6357_keys_resources, NULL, 0, 0,
+ "mediatek,mt6357-keys"),
};
/* MT6331 is always used in combination with MT6332 */
static const struct mfd_cell mt6331_mt6332_devs[] = {
- {
- .name = "mt6331-rtc",
- .num_resources = ARRAY_SIZE(mt6331_rtc_resources),
- .resources = mt6331_rtc_resources,
- .of_compatible = "mediatek,mt6331-rtc",
- }, {
- .name = "mt6331-regulator",
- .of_compatible = "mediatek,mt6331-regulator"
- }, {
- .name = "mt6332-regulator",
- .of_compatible = "mediatek,mt6332-regulator"
- }, {
- .name = "mt6331-keys",
- .num_resources = ARRAY_SIZE(mt6331_keys_resources),
- .resources = mt6331_keys_resources,
- .of_compatible = "mediatek,mt6331-keys"
- },
+ MFD_CELL_OF("mt6331-rtc", mt6331_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6331-rtc"),
+ MFD_CELL_OF("mt6331-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6331-regulator"),
+ MFD_CELL_OF("mt6332-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6332-regulator"),
+ MFD_CELL_OF("mt6331-keys", mt6331_keys_resources, NULL, 0, 0,
+ "mediatek,mt6331-keys"),
};
static const struct mfd_cell mt6358_devs[] = {
- {
- .name = "mt6359-auxadc",
- .of_compatible = "mediatek,mt6358-auxadc"
- }, {
- .name = "mt6358-regulator",
- .of_compatible = "mediatek,mt6358-regulator"
- }, {
- .name = "mt6358-rtc",
- .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
- .resources = mt6358_rtc_resources,
- .of_compatible = "mediatek,mt6358-rtc",
- }, {
- .name = "mt6358-sound",
- .of_compatible = "mediatek,mt6358-sound"
- }, {
- .name = "mt6358-keys",
- .num_resources = ARRAY_SIZE(mt6358_keys_resources),
- .resources = mt6358_keys_resources,
- .of_compatible = "mediatek,mt6358-keys"
- },
+ MFD_CELL_OF("mt6359-auxadc", NULL, NULL, 0, 0,
+ "mediatek,mt6358-auxadc"),
+ MFD_CELL_OF("mt6358-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6358-regulator"),
+ MFD_CELL_OF("mt6358-rtc", mt6358_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6358-rtc"),
+ MFD_CELL_OF("mt6358-sound", NULL, NULL, 0, 0,
+ "mediatek,mt6358-sound"),
+ MFD_CELL_OF("mt6358-keys", mt6358_keys_resources, NULL, 0, 0,
+ "mediatek,mt6358-keys"),
};
static const struct mfd_cell mt6359_devs[] = {
- {
- .name = "mt6359-auxadc",
- .of_compatible = "mediatek,mt6359-auxadc"
- },
- { .name = "mt6359-regulator", },
- {
- .name = "mt6359-rtc",
- .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
- .resources = mt6358_rtc_resources,
- .of_compatible = "mediatek,mt6358-rtc",
- },
- { .name = "mt6359-sound", },
- {
- .name = "mt6359-keys",
- .num_resources = ARRAY_SIZE(mt6359_keys_resources),
- .resources = mt6359_keys_resources,
- .of_compatible = "mediatek,mt6359-keys"
- },
- {
- .name = "mt6359-accdet",
- .of_compatible = "mediatek,mt6359-accdet",
- .num_resources = ARRAY_SIZE(mt6359_accdet_resources),
- .resources = mt6359_accdet_resources,
- },
+ MFD_CELL_OF("mt6359-auxadc", NULL, NULL, 0, 0,
+ "mediatek,mt6359-auxadc"),
+ MFD_CELL_NAME("mt6359-regulator"),
+ MFD_CELL_OF("mt6359-rtc", mt6358_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6358-rtc"),
+ MFD_CELL_NAME("mt6359-sound"),
+ MFD_CELL_OF("mt6359-keys", mt6359_keys_resources, NULL, 0, 0,
+ "mediatek,mt6359-keys"),
+ MFD_CELL_OF("mt6359-accdet", mt6359_accdet_resources, NULL, 0, 0,
+ "mediatek,mt6359-accdet"),
};
static const struct mfd_cell mt6397_devs[] = {
- {
- .name = "mt6397-rtc",
- .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
- .resources = mt6397_rtc_resources,
- .of_compatible = "mediatek,mt6397-rtc",
- }, {
- .name = "mt6397-regulator",
- .of_compatible = "mediatek,mt6397-regulator",
- }, {
- .name = "mt6397-codec",
- .of_compatible = "mediatek,mt6397-codec",
- }, {
- .name = "mt6397-clk",
- .of_compatible = "mediatek,mt6397-clk",
- }, {
- .name = "mt6397-pinctrl",
- .of_compatible = "mediatek,mt6397-pinctrl",
- }, {
- .name = "mt6397-keys",
- .num_resources = ARRAY_SIZE(mt6397_keys_resources),
- .resources = mt6397_keys_resources,
- .of_compatible = "mediatek,mt6397-keys"
- }
+ MFD_CELL_OF("mt6397-rtc", mt6397_rtc_resources, NULL, 0, 0,
+ "mediatek,mt6397-rtc"),
+ MFD_CELL_OF("mt6397-regulator", NULL, NULL, 0, 0,
+ "mediatek,mt6397-regulator"),
+ MFD_CELL_OF("mt6397-codec", NULL, NULL, 0, 0,
+ "mediatek,mt6397-codec"),
+ MFD_CELL_OF("mt6397-clk", NULL, NULL, 0, 0,
+ "mediatek,mt6397-clk"),
+ MFD_CELL_OF("mt6397-pinctrl", NULL, NULL, 0, 0,
+ "mediatek,mt6397-pinctrl"),
+ MFD_CELL_OF("mt6397-keys", mt6397_keys_resources, NULL, 0, 0,
+ "mediatek,mt6397-keys"),
};
struct chip_data {
--
2.43.0
^ permalink raw reply related
* [PATCH v6 2/7] dt-bindings: input: mtk-pmic-keys: Add MT6392 PMIC keys
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
AngeloGioacchino Del Regno, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger, Linus Walleij,
Louis-Alexis Eyraud, Julien Massot, Akari Tsuyukusa, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add the binding documentation of mtk-pmic-keys for the MT6392 PMIC.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
---
Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
index 140a862ecfbe..ff720588128b 100644
--- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
@@ -31,6 +31,7 @@ properties:
- mediatek,mt6357-keys
- mediatek,mt6358-keys
- mediatek,mt6359-keys
+ - mediatek,mt6392-keys
- mediatek,mt6397-keys
- items:
- enum:
--
2.43.0
^ permalink raw reply related
* [PATCH v6 1/7] dt-bindings: mfd: mt6397: Add MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Julien Massot,
Louis-Alexis Eyraud, Akari Tsuyukusa, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260612200717.361018-1-l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add the initial bindings for the MT6392 PMIC and its RTC device.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
.../devicetree/bindings/mfd/mediatek,mt6397.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 3cbc0dc12c31..e39e81aa9924 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -40,6 +40,10 @@ properties:
- mediatek,mt6358
- mediatek,mt6359
- mediatek,mt6397
+ - items:
+ - enum:
+ - mediatek,mt6392
+ - const: mediatek,mt6323
- items:
- enum:
- mediatek,mt6366
@@ -72,6 +76,10 @@ properties:
- mediatek,mt6331-rtc
- mediatek,mt6358-rtc
- mediatek,mt6397-rtc
+ - items:
+ - enum:
+ - mediatek,mt6392-rtc
+ - const: mediatek,mt6323-rtc
- items:
- enum:
- mediatek,mt6359-rtc
--
2.43.0
^ permalink raw reply related
* [PATCH v6 0/7] Add support for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-12 20:04 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Julien Massot,
Louis-Alexis Eyraud, Val Packett, Fabien Parent, Akari Tsuyukusa,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
The MediaTek MT6392 PMIC is usually found on devices powered by
the MT8516/MT8167 SoC and is yet another MT6323/MT6397 variant.
This series is mostly based around patches submitted a couple
years ago by Fabien Parent and not merged and from Val Packett's
submission from Jan 2025 that included extra cleanups, fixes, and a
new dtsi file similar to ones that exist for other PMICs. Some
comments weren't addressed and the series was ultimately not merged.
These patches only enable three functions: keys, pinctrl and RTC.
Regulators and speaker amp will follow later as I still need to further
improve those two, but getting the main PMIC in will make the series
easier to review.
I added a handful of device tree improvements to fix some dtbs_check
errors, added support for the pinctrl device and addressed the comments
from last year's reviews.
Please note that patch 0005 depends on patch 0004 as they both need the
registers.h file, but they belong to different driver areas. I'm not sure
if I'm supposed to squash them even if they belong to different driver
areas of if it's fine like this. Any advice is welcome.
The series has been tested on Xiaomi Mi Smart Clock X04G and on the
Lenovo Smart Clock 2.
Changes in v6:
- Dropped the regulators driver for the moment
- Explained the FCHR key name origin in the commit message
- Introduced the MFD_CELL_* macro in the sub-devices definitions.
A separate, independent commit introduced MFD_CELL_* to all the
subdevices in the mt6397-core.c file for consistency
- Replaced of_device_get_match_data with device_get_match_data
- Removed the mfd_match_data enum in favor of the preexisting
chip_id enum
- Adjusted the error message if the device is unsupported
Changes in v5 [5]:
- Double checked regulator driver with data sheet and Android sources.
The data sheet I have misses a lot of register descriptions, but
Android sources have been helpful to fill the gaps
- Reintroduced the required attribute for the regulator compatible
in the bindings
- Fixed the missing reference to the MT6392 schema
- Fixed casts/unused vars reported by kernel test robot
- Removed Reviewed-by tags from the regulator patches as they have been
modified in this version
Changes in v4 [4]:
- Dropped usage of the regulator compatible
- Fixed commit messages text to properly reference the target subsystem
- Added supply rails to the regulator
- Reworked the regulator schema and PMIC dtsi. Now all supplies are
documented and the schema no longer includes voltage information
- Removed redundant ldo- / buck- prefixes
- Renamed the pinfunc header to mediatek,mt6392-pinfunc.h
- Modified the MFD driver to use a simple identifier in the of_match
data properties
Changes in v3 [3]:
- Added pinctrl device
- Changed mt6397-rtc fallback to mt6323-rtc
- Added schema for regulators
- Fixed checkpatch issues
Changes in v2 [2]:
- Replaced explicit compatibles with fallbacks
Initial version: [1]
[1] https://lore.kernel.org/linux-mediatek/cover.1771865014.git.l.scorcia@gmail.com/
[2] https://lore.kernel.org/linux-mediatek/20260306120521.163654-1-l.scorcia@gmail.com/
[3] https://lore.kernel.org/linux-mediatek/20260317184507.523060-1-l.scorcia@gmail.com/
[4] https://lore.kernel.org/linux-mediatek/20260330083429.359819-1-l.scorcia@gmail.com/
[5] https://lore.kernel.org/linux-mediatek/20260420213529.1645560-1-l.scorcia@gmail.com/
Fabien Parent (3):
dt-bindings: mfd: mt6397: Add MT6392 PMIC
dt-bindings: input: mtk-pmic-keys: Add MT6392 PMIC keys
mfd: mt6397: Add support for MT6392 PMIC
Luca Leonardo Scorcia (2):
mfd: mt6397: Use MFD_CELL_* to describe sub-devices
pinctrl: mediatek: mt6397: Add MediaTek MT6392
Val Packett (2):
input: keyboard: mtk-pmic-keys: Add MT6392 support
arm64: dts: mediatek: Add MediaTek MT6392 PMIC dtsi
.../bindings/input/mediatek,pmic-keys.yaml | 1 +
.../bindings/mfd/mediatek,mt6397.yaml | 8 +
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 41 ++
drivers/input/keyboard/mtk-pmic-keys.c | 17 +
drivers/mfd/mt6397-core.c | 294 +++++------
drivers/mfd/mt6397-irq.c | 8 +
drivers/pinctrl/mediatek/pinctrl-mt6397.c | 37 +-
drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h | 64 +++
include/linux/mfd/mt6392/core.h | 43 ++
include/linux/mfd/mt6392/registers.h | 488 ++++++++++++++++++
include/linux/mfd/mt6397/core.h | 1 +
11 files changed, 840 insertions(+), 162 deletions(-)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
create mode 100644 include/linux/mfd/mt6392/core.h
create mode 100644 include/linux/mfd/mt6392/registers.h
--
2.43.0
^ permalink raw reply
* [PATCH] [wireless-next v2] wifi: mt76: fix airoha_npu dependency tracking
From: Arnd Bergmann @ 2026-06-12 20:13 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
AngeloGioacchino Del Regno
Cc: Arnd Bergmann, Shayne Chen, Sean Wang, Matthias Brugger, Rex Lu,
Sujuan Chen, Benjamin Lin, linux-wireless, linux-kernel,
linux-mediatek
From: Arnd Bergmann <arnd@arndb.de>
There is a new build failure with MT7996E=m MT76_CORE=y and NET_AIROHA_NPU=m:
ld.lld: error: undefined symbol: airoha_npu_get
ld.lld: error: undefined symbol: airoha_npu_put
>>> referenced by npu.c
>>> drivers/net/wireless/mediatek/mt76/npu.o:(mt76_npu_init) in archive vmlinux.a
Fix this by reworking the dependency for the MT7996_NPU to only
allow enabling that when mt76_core can link against the npu driver.
To make sure this gets caught more easily in the future when additional
mt76 variants need the same dependency, also turn CONFIG_MT76_NPU into
a tristate symbol that has the same dependency.
Fixes: 7fb554b1b623 ("wifi: mt76: Introduce the NPU generic layer")
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
----
v2: fix typo s/MT76/MT76_CORE/
---
drivers/net/wireless/mediatek/mt76/Kconfig | 4 ++--
drivers/net/wireless/mediatek/mt76/Makefile | 6 +++++-
drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7996/Kconfig | 2 +-
4 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig
index 502303622a53..2ca96e0527c0 100644
--- a/drivers/net/wireless/mediatek/mt76/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/Kconfig
@@ -38,8 +38,8 @@ config MT792x_USB
select MT76_USB
config MT76_NPU
- bool
- depends on MT76_CORE
+ tristate
+ depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU
source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile
index 1d42adfe8030..cacdd2b13d05 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -12,7 +12,11 @@ mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
tx.o agg-rx.o mcu.o wed.o scan.o channel.o
-mt76-$(CONFIG_MT76_NPU) += npu.o
+ifdef CONFIG_MT76_NPU
+# CONFIG_MT76_NPU is tristate to simplify dependency tracking,
+# but it behaves as a bool symbol here.
+mt76-y += npu.o
+endif
mt76-$(CONFIG_PCI) += pci.o
mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 07955555f84d..60bd155cc7d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1647,7 +1647,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len);
-#ifdef CONFIG_MT76_NPU
+#if IS_ENABLED(CONFIG_MT76_NPU)
void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb,
u32 info);
int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
index 5503d03bf62c..5742bce12fbb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
@@ -16,6 +16,6 @@ config MT7996E
config MT7996_NPU
bool "MT7996 (PCIe) NPU support"
depends on MT7996E
- depends on NET_AIROHA_NPU=y || MT7996E=NET_AIROHA_NPU
+ depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU
select MT76_NPU
default n
--
2.39.5
^ permalink raw reply related
* Re: [PATCH] wifi: mt76: fix airoha_npu dependency tracking
From: Arnd Bergmann @ 2026-06-12 19:43 UTC (permalink / raw)
To: Arnd Bergmann, Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Shayne Chen, Sean Wang, Rex Lu, linux-wireless, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <20260611125912.3387021-1-arnd@kernel.org>
On Thu, Jun 11, 2026, at 14:58, Arnd Bergmann wrote:
>
> config MT76_NPU
> - bool
> - depends on MT76_CORE
> + tristate
> + depends on NET_AIROHA_NPU=y || MT76=NET_AIROHA_NPU
>
Further testing showed that there is a typo here, it should
be MT76_CORE instead of MT76.
I'll send a v2 patch.
Arnd
^ permalink raw reply
* Re: [PATCH net-next] net: airoha: better handle MIBs for GDM ports with multiple devs attached
From: Simon Horman @ 2026-06-12 17:08 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-arm-kernel, linux-mediatek, netdev,
Christian Marangi
In-Reply-To: <20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org>
On Thu, Jun 11, 2026 at 12:43:00PM +0200, Lorenzo Bianconi wrote:
> In the context of a GDM port that can have multiple net_devices attached
> (GDM3 and GDM4), the HW counters (MIBs) are global for the GDM port.
> This cause duplicated stats reported to the kernel for the related
> net_device.
> The SoC supports a split MIB feature where each counter is tracked based
> on the relevant HW channel (NBQ) to account for this scenario and
> provide a way to select the related counter on accessing the MIB
> registers.
> Enable this feature for GDM3 and GDM4 and configure the relevant HW
> channel before updating the HW stats to report correct HW counter to the
> kernel for the related interface.
> Move the stats struct from port to dev since HW counter are now specific
> to the network device instead of the GDM port. Refactor
> airoha_update_hw_stats() to take airoha_eth and airoha_gdm_port
> parameters since the function operates on the entire port.
>
> Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* Re: [PATCH v3 1/3] dt-bindings: mfd: syscon: Disallow simple-bus with syscon
From: Rob Herring (Arm) @ 2026-06-12 16:22 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Roger Quadros, linux-omap, Andreas Kemnade, Kevin Hilman,
Jacky Huang, Tony Lindgren, linux-rockchip, Conor Dooley,
Lee Jones, Heiko Stuebner, AngeloGioacchino Del Regno,
Matthias Brugger, Krzysztof Kozlowski, devicetree, Shan-Chun Hung,
linux-kernel, linux-renesas-soc, Magnus Damm, Geert Uytterhoeven,
Aaro Koskinen, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260608-n-dt-bindings-simple-bus-syscon-v3-1-4eba9ec1212a@oss.qualcomm.com>
On Mon, 08 Jun 2026 22:44:24 +0200, Krzysztof Kozlowski wrote:
> "syscon" is a system controller with registers having their own
> functions, thus not really a trivial MMIO simple bus. "simple-bus" on
> the other hand is just a bus on which multiple devices sit and the
> "simple" means no functions are allowed here.
>
> Combination of both "syscon" and "simple-bus" is abuse of DT for easier
> instantiating of Linux device drivers so add a schema to disallow that.
>
> Unfortunately there are a few old cases of that patterns, so add
> exceptions:
>
> 1. "cznic,turris1x-cpld" and "img,pistachio-cr-periph" are already used
> in upstream DTS.
>
> 2. TI has several DTSI with a child of SCM device (e.g. "ti,am3-scm")
> using "syscon" and "simple-bus" but without a dedicated compatible
> documented anywhere. Add new compatibles for such cases.
>
> Additionally, add comments around code enforcing two or three
> compatibles: it is similar safeguard detecting incorrect bindings.
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>
> ---
>
> Changes in v3:
> 1. s/ti,omap5-scm-conf/ti,omap5-sysc-padconf-global/ because it is more
> appropriate (specific)
> 2. Add comments, why simple-mfd+syscon has dedicated if:then:
>
> Changes in v2:
> 1. Complete patch. I accidentally sent only part of it, built on top of
> internal WIP which I forgot to squash.
> I received Ack from Rob, but change is significant, so please kindly
> re-review.
> ---
> .../devicetree/bindings/mfd/syscon-common.yaml | 34 ++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: Rob Herring (Arm) @ 2026-06-12 14:32 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: linux-mediatek, linux-kernel, Lorenzo Pieralisi, Conor Dooley,
Ryder Lee, Manivannan Sadhasivam, Bjorn Helgaas,
Krzysztof Wilczyński, Krzysztof Kozlowski, linux-pci,
Matthias Brugger, devicetree, AngeloGioacchino Del Regno
In-Reply-To: <20260508063633.3894348-1-wenst@chromium.org>
On Fri, 08 May 2026 14:36:32 +0800, Chen-Yu Tsai wrote:
> On some SoCs without an IOMMU behind the PCIe controller, the PCIe
> controller memory access could be limited to a small region by the
> firmware configuring a memory protection unit. This memory region
> must be assigned to the PCIe controller so that the OS knows to
> use that region. Otherwise PCIe devices would not work properly.
>
> Allow the memory-region property with one item pointing to a
> restricted DMA buffer.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> This patch compliments another patch that moved the memory-region from
> the PCIe device to the PCIe controller [1].
>
> [1] https://lore.kernel.org/all/20260430120725.241779-1-wenst@chromium.org/
>
> Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml | 4 ++++
> 1 file changed, 4 insertions(+)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next] net: airoha: better handle MIBs for GDM ports with multiple devs attached
From: Lorenzo Bianconi @ 2026-06-12 14:20 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: linux-arm-kernel, linux-mediatek, netdev, Christian Marangi
In-Reply-To: <20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 9780 bytes --]
> In the context of a GDM port that can have multiple net_devices attached
> (GDM3 and GDM4), the HW counters (MIBs) are global for the GDM port.
> This cause duplicated stats reported to the kernel for the related
> net_device.
> The SoC supports a split MIB feature where each counter is tracked based
> on the relevant HW channel (NBQ) to account for this scenario and
> provide a way to select the related counter on accessing the MIB
> registers.
> Enable this feature for GDM3 and GDM4 and configure the relevant HW
> channel before updating the HW stats to report correct HW counter to the
> kernel for the related interface.
> Move the stats struct from port to dev since HW counter are now specific
> to the network device instead of the GDM port. Refactor
> airoha_update_hw_stats() to take airoha_eth and airoha_gdm_port
> parameters since the function operates on the entire port.
>
> Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 191 +++++++++++++++++--------------
> drivers/net/ethernet/airoha/airoha_eth.h | 7 +-
> 2 files changed, 112 insertions(+), 86 deletions(-)
>
[...]
> - airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id),
> +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
> +{
> + struct airoha_gdm_port *port = dev->port;
> + int i;
> +
> + spin_lock(&port->stats_lock);
> +
> + for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
> + if (port->devs[i])
> + airoha_dev_get_hw_stats(port->devs[i]);
> + }
> +
> + /* Reset MIB counters */
> + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id),
> FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK);
commenting on sashiko's report:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064%40kernel.org
- With split MIB enabled on GDM3/GDM4, airoha_dev_get_hw_stats() programs
REG_FE_GDM_MIB_CFG with the device's nbq before reading per-channel
counters, so the FE_TX_MIB_ID/FE_RX_MIB_ID selector clearly gates the
counter reads.
After the loop in airoha_update_hw_stats(), MIB_CFG retains the last
iterated device's nbq, and a single airoha_fe_set() is issued against
REG_FE_GDM_MIB_CLEAR. REG_FE_GDM_MIB_CLEAR exposes only RX/TX bits with no
separate per-channel selector.
If, as is typical of split-MIB designs, the clear honors the same
FE_TX_MIB_ID/FE_RX_MIB_ID selector used for reads, will only the last
iterated device's HW counters be cleared each cycle?
Since airoha_dev_get_hw_stats() accumulates with += on each read, would
the un-cleared HW counters of the other devs keep being re-added to
dev->stats on every fetch, yielding inflated stats and eventual HW
counter overflow?
Would moving the MIB_CLEAR write inside the per-device loop, while that
device's nbq is still selected in MIB_CFG, address this if the clear is
indeed per-channel? Or can the datasheet confirm REG_FE_GDM_MIB_CLEAR is
strictly global and unaffected by split mode?
- This is the same report available in [0].
REG_FE_GDM_MIB_CLEAR is global and it clears all nbq counters for the port.
Regards,
Lorenzo
[0] https://sashiko.dev/#/patchset/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064%40kernel.org
>
> - u64_stats_update_end(&port->stats.syncp);
> - spin_unlock(&port->stats.lock);
> + spin_unlock(&port->stats_lock);
> }
>
> static int airoha_dev_open(struct net_device *netdev)
> @@ -2043,23 +2071,22 @@ static void airoha_dev_get_stats64(struct net_device *netdev,
> struct rtnl_link_stats64 *storage)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> airoha_update_hw_stats(dev);
> do {
> - start = u64_stats_fetch_begin(&port->stats.syncp);
> - storage->rx_packets = port->stats.rx_ok_pkts;
> - storage->tx_packets = port->stats.tx_ok_pkts;
> - storage->rx_bytes = port->stats.rx_ok_bytes;
> - storage->tx_bytes = port->stats.tx_ok_bytes;
> - storage->multicast = port->stats.rx_multicast;
> - storage->rx_errors = port->stats.rx_errors;
> - storage->rx_dropped = port->stats.rx_drops;
> - storage->tx_dropped = port->stats.tx_drops;
> - storage->rx_crc_errors = port->stats.rx_crc_error;
> - storage->rx_over_errors = port->stats.rx_over_errors;
> - } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> + start = u64_stats_fetch_begin(&dev->stats.syncp);
> + storage->rx_packets = dev->stats.rx_ok_pkts;
> + storage->tx_packets = dev->stats.tx_ok_pkts;
> + storage->rx_bytes = dev->stats.rx_ok_bytes;
> + storage->tx_bytes = dev->stats.tx_ok_bytes;
> + storage->multicast = dev->stats.rx_multicast;
> + storage->rx_errors = dev->stats.rx_errors;
> + storage->rx_dropped = dev->stats.rx_drops;
> + storage->tx_dropped = dev->stats.tx_drops;
> + storage->rx_crc_errors = dev->stats.rx_crc_error;
> + storage->rx_over_errors = dev->stats.rx_over_errors;
> + } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
> }
>
> static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
> @@ -2310,20 +2337,19 @@ static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
> struct ethtool_eth_mac_stats *stats)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> airoha_update_hw_stats(dev);
> do {
> - start = u64_stats_fetch_begin(&port->stats.syncp);
> - stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
> - stats->OctetsTransmittedOK = port->stats.tx_ok_bytes;
> - stats->MulticastFramesXmittedOK = port->stats.tx_multicast;
> - stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast;
> - stats->FramesReceivedOK = port->stats.rx_ok_pkts;
> - stats->OctetsReceivedOK = port->stats.rx_ok_bytes;
> - stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast;
> - } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> + start = u64_stats_fetch_begin(&dev->stats.syncp);
> + stats->FramesTransmittedOK = dev->stats.tx_ok_pkts;
> + stats->OctetsTransmittedOK = dev->stats.tx_ok_bytes;
> + stats->MulticastFramesXmittedOK = dev->stats.tx_multicast;
> + stats->BroadcastFramesXmittedOK = dev->stats.tx_broadcast;
> + stats->FramesReceivedOK = dev->stats.rx_ok_pkts;
> + stats->OctetsReceivedOK = dev->stats.rx_ok_bytes;
> + stats->BroadcastFramesReceivedOK = dev->stats.rx_broadcast;
> + } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
> }
>
> static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = {
> @@ -2343,8 +2369,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> const struct ethtool_rmon_hist_range **ranges)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> - struct airoha_hw_stats *hw_stats = &port->stats;
> + struct airoha_hw_stats *hw_stats = &dev->stats;
> unsigned int start;
>
> BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) !=
> @@ -2357,7 +2382,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> do {
> int i;
>
> - start = u64_stats_fetch_begin(&port->stats.syncp);
> + start = u64_stats_fetch_begin(&dev->stats.syncp);
> stats->fragments = hw_stats->rx_fragment;
> stats->jabbers = hw_stats->rx_jabber;
> for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1;
> @@ -2365,7 +2390,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> stats->hist[i] = hw_stats->rx_len[i];
> stats->hist_tx[i] = hw_stats->tx_len[i];
> }
> - } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> + } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
> }
>
> static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> @@ -3205,6 +3230,7 @@ static int airoha_alloc_gdm_device(struct airoha_eth *eth,
>
> netdev->dev.of_node = of_node_get(np);
> dev = netdev_priv(netdev);
> + u64_stats_init(&dev->stats.syncp);
> dev->port = port;
> dev->eth = eth;
> dev->nbq = nbq;
> @@ -3244,9 +3270,8 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> if (!port)
> return -ENOMEM;
>
> - u64_stats_init(&port->stats.syncp);
> - spin_lock_init(&port->stats.lock);
> port->id = id;
> + spin_lock_init(&port->stats_lock);
> eth->ports[p] = port;
>
> err = airoha_metadata_dst_alloc(port);
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 8f42973f9cf5..46b1c31939de 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -215,8 +215,6 @@ struct airoha_tx_irq_queue {
> };
>
> struct airoha_hw_stats {
> - /* protect concurrent hw_stats accesses */
> - spinlock_t lock;
> struct u64_stats_sync syncp;
>
> /* get_stats64 */
> @@ -554,6 +552,8 @@ struct airoha_gdm_dev {
>
> u32 flags;
> int nbq;
> +
> + struct airoha_hw_stats stats;
> };
>
> struct airoha_gdm_port {
> @@ -561,7 +561,8 @@ struct airoha_gdm_port {
> int id;
> int users;
>
> - struct airoha_hw_stats stats;
> + /* protect concurrent hw_stats accesses */
> + spinlock_t stats_lock;
>
> struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS];
> };
>
> ---
> base-commit: c8459ee2fef502d6ef6c063751c33d9ac7943eab
> change-id: 20260611-airoha-eth-multi-serdes-stats-df2dc16c2dd6
>
> Best regards,
> --
> Lorenzo Bianconi <lorenzo@kernel.org>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] wifi: mt76: fix airoha_npu dependency tracking
From: Lorenzo Bianconi @ 2026-06-12 13:49 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Felix Fietkau, Ryder Lee, Matthias Brugger,
AngeloGioacchino Del Regno, Arnd Bergmann, Shayne Chen, Sean Wang,
Rex Lu, linux-wireless, linux-kernel, linux-arm-kernel,
linux-mediatek
In-Reply-To: <20260611125912.3387021-1-arnd@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 3761 bytes --]
> From: Arnd Bergmann <arnd@arndb.de>
>
> There is a new build failure with MT7996E=m MT76_CORE=y and NET_AIROHA_NPU=m:
>
> ld.lld: error: undefined symbol: airoha_npu_get
> ld.lld: error: undefined symbol: airoha_npu_put
> >>> referenced by npu.c
> >>> drivers/net/wireless/mediatek/mt76/npu.o:(mt76_npu_init) in archive vmlinux.a
>
> Fix this by reworking the dependency for the MT7996_NPU to only
> allow enabling that when mt76_core can link against the npu driver.
>
> To make sure this gets caught more easily in the future when additional
> mt76 variants need the same dependency, also turn CONFIG_MT76_NPU into
> a tristate symbol that has the same dependency.
>
> Fixes: 7fb554b1b623 ("wifi: mt76: Introduce the NPU generic layer")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/Kconfig | 4 ++--
> drivers/net/wireless/mediatek/mt76/Makefile | 6 +++++-
> drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
> drivers/net/wireless/mediatek/mt76/mt7996/Kconfig | 2 +-
> 4 files changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig
> index 502303622a53..d941e67a222d 100644
> --- a/drivers/net/wireless/mediatek/mt76/Kconfig
> +++ b/drivers/net/wireless/mediatek/mt76/Kconfig
> @@ -38,8 +38,8 @@ config MT792x_USB
> select MT76_USB
>
> config MT76_NPU
> - bool
> - depends on MT76_CORE
> + tristate
> + depends on NET_AIROHA_NPU=y || MT76=NET_AIROHA_NPU
>
> source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
> source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
> diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile
> index 1d42adfe8030..cacdd2b13d05 100644
> --- a/drivers/net/wireless/mediatek/mt76/Makefile
> +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> @@ -12,7 +12,11 @@ mt76-y := \
> mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
> tx.o agg-rx.o mcu.o wed.o scan.o channel.o
>
> -mt76-$(CONFIG_MT76_NPU) += npu.o
> +ifdef CONFIG_MT76_NPU
> +# CONFIG_MT76_NPU is tristate to simplify dependency tracking,
> +# but it behaves as a bool symbol here.
> +mt76-y += npu.o
> +endif
> mt76-$(CONFIG_PCI) += pci.o
> mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 07955555f84d..60bd155cc7d5 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -1647,7 +1647,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
> int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
> int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len);
>
> -#ifdef CONFIG_MT76_NPU
> +#if IS_ENABLED(CONFIG_MT76_NPU)
> void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb,
> u32 info);
> int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
> index 5503d03bf62c..5742bce12fbb 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
> @@ -16,6 +16,6 @@ config MT7996E
> config MT7996_NPU
> bool "MT7996 (PCIe) NPU support"
> depends on MT7996E
> - depends on NET_AIROHA_NPU=y || MT7996E=NET_AIROHA_NPU
> + depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU
> select MT76_NPU
> default n
> --
> 2.39.5
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next] net: airoha: better handle MIBs for GDM ports with multiple devs attached
From: Lorenzo Bianconi @ 2026-06-12 11:04 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: linux-arm-kernel, linux-mediatek, netdev, Christian Marangi
In-Reply-To: <20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 9195 bytes --]
> In the context of a GDM port that can have multiple net_devices attached
> (GDM3 and GDM4), the HW counters (MIBs) are global for the GDM port.
> This cause duplicated stats reported to the kernel for the related
> net_device.
> The SoC supports a split MIB feature where each counter is tracked based
> on the relevant HW channel (NBQ) to account for this scenario and
> provide a way to select the related counter on accessing the MIB
> registers.
> Enable this feature for GDM3 and GDM4 and configure the relevant HW
> channel before updating the HW stats to report correct HW counter to the
> kernel for the related interface.
> Move the stats struct from port to dev since HW counter are now specific
> to the network device instead of the GDM port. Refactor
> airoha_update_hw_stats() to take airoha_eth and airoha_gdm_port
> parameters since the function operates on the entire port.
>
> Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
commenting on sashiko's report:
https://sashiko.dev/#/patchset/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064%40kernel.org
[...]
>
> - /* reset mib counters */
> - airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id),
> +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
> +{
> + struct airoha_gdm_port *port = dev->port;
> + int i;
> +
> + spin_lock(&port->stats_lock);
> +
> + for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
> + if (port->devs[i])
> + airoha_dev_get_hw_stats(port->devs[i]);
> + }
> +
> + /* Reset MIB counters */
> + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id),
> FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK);
- Does clearing the MIB counters outside the device loop cause issues with the
split MIB feature?
airoha_dev_get_hw_stats() modifies REG_FE_GDM_MIB_CFG to select the specific
nbq channel. Since REG_FE_GDM_MIB_CLEAR is called after the loop, does it only
clear the hardware counters for the last selected nbq? If so, the uncleared
counters for the other channels might accumulate in hardware, and adding them
repeatedly to the software stats (e.g., dev->stats.tx_ok_pkts += val) could
result in exponential growth.
Alternatively, if REG_FE_GDM_MIB_CLEAR globally clears all nbq counters for
the port, calling it here could drop packets that arrived for earlier devices
between their respective read operations and this clear.
- REG_FE_GDM_MIB_CLEAR is global and it clears all nbq counters for the port.
There's a tiny window where packets arriving for dev[0] between its read
and the global clear are lost, but that's microseconds of register reads,
so I guess that's negligible.
Regards,
Lorenzo
>
> - u64_stats_update_end(&port->stats.syncp);
> - spin_unlock(&port->stats.lock);
> + spin_unlock(&port->stats_lock);
> }
>
> static int airoha_dev_open(struct net_device *netdev)
> @@ -2043,23 +2071,22 @@ static void airoha_dev_get_stats64(struct net_device *netdev,
> struct rtnl_link_stats64 *storage)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> airoha_update_hw_stats(dev);
> do {
> - start = u64_stats_fetch_begin(&port->stats.syncp);
> - storage->rx_packets = port->stats.rx_ok_pkts;
> - storage->tx_packets = port->stats.tx_ok_pkts;
> - storage->rx_bytes = port->stats.rx_ok_bytes;
> - storage->tx_bytes = port->stats.tx_ok_bytes;
> - storage->multicast = port->stats.rx_multicast;
> - storage->rx_errors = port->stats.rx_errors;
> - storage->rx_dropped = port->stats.rx_drops;
> - storage->tx_dropped = port->stats.tx_drops;
> - storage->rx_crc_errors = port->stats.rx_crc_error;
> - storage->rx_over_errors = port->stats.rx_over_errors;
> - } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> + start = u64_stats_fetch_begin(&dev->stats.syncp);
> + storage->rx_packets = dev->stats.rx_ok_pkts;
> + storage->tx_packets = dev->stats.tx_ok_pkts;
> + storage->rx_bytes = dev->stats.rx_ok_bytes;
> + storage->tx_bytes = dev->stats.tx_ok_bytes;
> + storage->multicast = dev->stats.rx_multicast;
> + storage->rx_errors = dev->stats.rx_errors;
> + storage->rx_dropped = dev->stats.rx_drops;
> + storage->tx_dropped = dev->stats.tx_drops;
> + storage->rx_crc_errors = dev->stats.rx_crc_error;
> + storage->rx_over_errors = dev->stats.rx_over_errors;
> + } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
> }
>
> static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
> @@ -2310,20 +2337,19 @@ static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
> struct ethtool_eth_mac_stats *stats)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> airoha_update_hw_stats(dev);
> do {
> - start = u64_stats_fetch_begin(&port->stats.syncp);
> - stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
> - stats->OctetsTransmittedOK = port->stats.tx_ok_bytes;
> - stats->MulticastFramesXmittedOK = port->stats.tx_multicast;
> - stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast;
> - stats->FramesReceivedOK = port->stats.rx_ok_pkts;
> - stats->OctetsReceivedOK = port->stats.rx_ok_bytes;
> - stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast;
> - } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> + start = u64_stats_fetch_begin(&dev->stats.syncp);
> + stats->FramesTransmittedOK = dev->stats.tx_ok_pkts;
> + stats->OctetsTransmittedOK = dev->stats.tx_ok_bytes;
> + stats->MulticastFramesXmittedOK = dev->stats.tx_multicast;
> + stats->BroadcastFramesXmittedOK = dev->stats.tx_broadcast;
> + stats->FramesReceivedOK = dev->stats.rx_ok_pkts;
> + stats->OctetsReceivedOK = dev->stats.rx_ok_bytes;
> + stats->BroadcastFramesReceivedOK = dev->stats.rx_broadcast;
> + } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
> }
>
> static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = {
> @@ -2343,8 +2369,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> const struct ethtool_rmon_hist_range **ranges)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> - struct airoha_hw_stats *hw_stats = &port->stats;
> + struct airoha_hw_stats *hw_stats = &dev->stats;
> unsigned int start;
>
> BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) !=
> @@ -2357,7 +2382,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> do {
> int i;
>
> - start = u64_stats_fetch_begin(&port->stats.syncp);
> + start = u64_stats_fetch_begin(&dev->stats.syncp);
> stats->fragments = hw_stats->rx_fragment;
> stats->jabbers = hw_stats->rx_jabber;
> for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1;
> @@ -2365,7 +2390,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> stats->hist[i] = hw_stats->rx_len[i];
> stats->hist_tx[i] = hw_stats->tx_len[i];
> }
> - } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> + } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
> }
>
> static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> @@ -3205,6 +3230,7 @@ static int airoha_alloc_gdm_device(struct airoha_eth *eth,
>
> netdev->dev.of_node = of_node_get(np);
> dev = netdev_priv(netdev);
> + u64_stats_init(&dev->stats.syncp);
> dev->port = port;
> dev->eth = eth;
> dev->nbq = nbq;
> @@ -3244,9 +3270,8 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> if (!port)
> return -ENOMEM;
>
> - u64_stats_init(&port->stats.syncp);
> - spin_lock_init(&port->stats.lock);
> port->id = id;
> + spin_lock_init(&port->stats_lock);
> eth->ports[p] = port;
>
> err = airoha_metadata_dst_alloc(port);
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 8f42973f9cf5..46b1c31939de 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -215,8 +215,6 @@ struct airoha_tx_irq_queue {
> };
>
> struct airoha_hw_stats {
> - /* protect concurrent hw_stats accesses */
> - spinlock_t lock;
> struct u64_stats_sync syncp;
>
> /* get_stats64 */
> @@ -554,6 +552,8 @@ struct airoha_gdm_dev {
>
> u32 flags;
> int nbq;
> +
> + struct airoha_hw_stats stats;
> };
>
> struct airoha_gdm_port {
> @@ -561,7 +561,8 @@ struct airoha_gdm_port {
> int id;
> int users;
>
> - struct airoha_hw_stats stats;
> + /* protect concurrent hw_stats accesses */
> + spinlock_t stats_lock;
>
> struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS];
> };
>
> ---
> base-commit: c8459ee2fef502d6ef6c063751c33d9ac7943eab
> change-id: 20260611-airoha-eth-multi-serdes-stats-df2dc16c2dd6
>
> Best regards,
> --
> Lorenzo Bianconi <lorenzo@kernel.org>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2] net: airoha: Fix debugfs new-tuple display for IPv4 ROUTE entries
From: Lorenzo Bianconi @ 2026-06-12 10:58 UTC (permalink / raw)
To: Wayen.Yan
Cc: netdev, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <6a2be54b.ef98c1b2.3c3224.2ed8@mx.google.com>
[-- Attachment #1: Type: text/plain, Size: 1764 bytes --]
> In airoha_ppe_debugfs_foe_show(), the second switch statement falls
> through from PPE_PKT_TYPE_IPV4_HNAPT/DSLITE to PPE_PKT_TYPE_IPV4_ROUTE,
> accessing hwe->ipv4.new_tuple for all three types. However, IPv4 ROUTE
> (3-tuple) entries do not contain a valid new_tuple — this field is only
> meaningful for NATted flows (HNAPT/DSLITE). For ROUTE entries, the
> memory at the new_tuple offset holds routing information, not NAT data,
> so displaying "new=" produces garbage output.
>
> Display new_tuple only for HNAPT and DSLITE, and let IPV4_ROUTE fall
> through to the default case.
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
>
> Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support")
> Link: https://lore.kernel.org/netdev/6a2b40ea.4dd82583.3a5c46.e5a2@mx.google.com/
> Signed-off-by: Wayen.Yan <win847@gmail.com>
> - Drop redundant PPE_PKT_TYPE_IPV4_ROUTE case, let it fall to default
> Changes in v2:
>
> ---
> drivers/net/ethernet/airoha/airoha_ppe_debugfs.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
> index 0112c41..e46a985 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
> @@ -121,8 +121,6 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
> case PPE_PKT_TYPE_IPV4_DSLITE:
> src_port = &hwe->ipv4.new_tuple.src_port;
> dest_port = &hwe->ipv4.new_tuple.dest_port;
> - fallthrough;
> - case PPE_PKT_TYPE_IPV4_ROUTE:
> src_addr = &hwe->ipv4.new_tuple.src_ip;
> dest_addr = &hwe->ipv4.new_tuple.dest_ip;
> seq_puts(m, " new=");
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH v2] net: airoha: Fix debugfs new-tuple display for IPv4 ROUTE entries
From: Wayen.Yan @ 2026-06-11 23:09 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In airoha_ppe_debugfs_foe_show(), the second switch statement falls
through from PPE_PKT_TYPE_IPV4_HNAPT/DSLITE to PPE_PKT_TYPE_IPV4_ROUTE,
accessing hwe->ipv4.new_tuple for all three types. However, IPv4 ROUTE
(3-tuple) entries do not contain a valid new_tuple — this field is only
meaningful for NATted flows (HNAPT/DSLITE). For ROUTE entries, the
memory at the new_tuple offset holds routing information, not NAT data,
so displaying "new=" produces garbage output.
Display new_tuple only for HNAPT and DSLITE, and let IPV4_ROUTE fall
through to the default case.
Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support")
Link: https://lore.kernel.org/netdev/6a2b40ea.4dd82583.3a5c46.e5a2@mx.google.com/
Signed-off-by: Wayen.Yan <win847@gmail.com>
- Drop redundant PPE_PKT_TYPE_IPV4_ROUTE case, let it fall to default
Changes in v2:
---
drivers/net/ethernet/airoha/airoha_ppe_debugfs.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
index 0112c41..e46a985 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
@@ -121,8 +121,6 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
case PPE_PKT_TYPE_IPV4_DSLITE:
src_port = &hwe->ipv4.new_tuple.src_port;
dest_port = &hwe->ipv4.new_tuple.dest_port;
- fallthrough;
- case PPE_PKT_TYPE_IPV4_ROUTE:
src_addr = &hwe->ipv4.new_tuple.src_ip;
dest_addr = &hwe->ipv4.new_tuple.dest_ip;
seq_puts(m, " new=");
--
2.51.0
^ permalink raw reply related
* Re: [PATCH] net: airoha: Fix debugfs new-tuple display for IPv4 ROUTE entries
From: Lorenzo Bianconi @ 2026-06-12 10:31 UTC (permalink / raw)
To: Wayen.Yan; +Cc: netdev, linux-arm-kernel, linux-mediatek
In-Reply-To: <6a2b40ea.4dd82583.3a5c46.e5a2@mx.google.com>
[-- Attachment #1: Type: text/plain, Size: 1971 bytes --]
> In airoha_ppe_debugfs_foe_show(), the second switch statement falls
> through from PPE_PKT_TYPE_IPV4_HNAPT/DSLITE to PPE_PKT_TYPE_IPV4_ROUTE,
> accessing hwe->ipv4.new_tuple for all three types. However, IPv4 ROUTE
> (3-tuple) entries do not contain a valid new_tuple — this field is only
> meaningful for NATted flows (HNAPT/DSLITE). For ROUTE entries, the
> memory at the new_tuple offset holds routing information, not NAT data,
> so displaying "new=" produces garbage output.
>
> Split the fallthrough: display new_tuple only for HNAPT and DSLITE, and
> add an explicit empty case for IPV4_ROUTE.
>
> Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support")
> Signed-off-by: Wayen.Yan <win847@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_ppe_debugfs.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
> index 0112c41..f9c12e7 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
> @@ -121,8 +121,6 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
> case PPE_PKT_TYPE_IPV4_DSLITE:
> src_port = &hwe->ipv4.new_tuple.src_port;
> dest_port = &hwe->ipv4.new_tuple.dest_port;
> - fallthrough;
> - case PPE_PKT_TYPE_IPV4_ROUTE:
> src_addr = &hwe->ipv4.new_tuple.src_ip;
> dest_addr = &hwe->ipv4.new_tuple.dest_ip;
> seq_puts(m, " new=");
> @@ -130,6 +128,8 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
> src_port, dest_port,
> ipv6);
> break;
> + case PPE_PKT_TYPE_IPV4_ROUTE:
I guess you can just drop PPE_PKT_TYPE_IPV4_ROUTE and use the default case.
Fixing it:
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> + break;
> default:
> break;
> }
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next 8/8] net: dsa: mt7530: implement port_change_conduit op
From: Daniel Golle @ 2026-06-12 10:29 UTC (permalink / raw)
To: Chester A. Unal
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, Russell King, netdev, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <02ad5de0-ea6a-4267-8686-72e3f98fce4e@arinc9.com>
On Fri, Jun 12, 2026 at 07:36:35AM +0000, Chester A. Unal wrote:
> On 10/06/2026 20:56, Daniel Golle wrote:
> > Allow changing the CPU port affinity of user ports at runtime via
> > the IFLA_DSA_CONDUIT netlink attribute. This updates the port matrix
> > to forward to the new CPU port instead of the old one.
> >
> > Signed-off-by: Daniel Golle <daniel@makrotopia.org>
>
> Fabulous!
>
> Acked-by: Chester A. Unal <chester.a.unal@arinc9.com>
>
> > ---
> > drivers/net/dsa/mt7530.c | 29 +++++++++++++++++++++++++++++
> > 1 file changed, 29 insertions(+)
> >
> > diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
> > index c96420c291d5..2f3e734b9f53 100644
> > --- a/drivers/net/dsa/mt7530.c
> > +++ b/drivers/net/dsa/mt7530.c
> > @@ -3206,6 +3206,34 @@ static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
> > return 0;
> > }
> > +static int
> > +mt753x_port_change_conduit(struct dsa_switch *ds, int port,
> > + struct net_device *conduit,
> > + struct netlink_ext_ack *extack)
> > +{
> > + struct dsa_port *new_cpu_dp = conduit->dsa_ptr;
> > + struct dsa_port *dp = dsa_to_port(ds, port);
> > + struct mt7530_priv *priv = ds->priv;
> > +
> > + if (priv->id != ID_MT7531)
> > + return -EOPNOTSUPP;
>
> Why do we limit this to MT7531 only?
I could test it only on MT7531 (BPi R64), and that's also where it
makes most sense imho: On MT7530 we got PHY muxing, on the MMIO
switches we physically got only a single CPU port.
^ permalink raw reply
* Re: [PATCH] net: airoha: Fix register index for Tx-fwd counter configuration
From: Lorenzo Bianconi @ 2026-06-12 10:28 UTC (permalink / raw)
To: Wayen.Yan; +Cc: netdev, linux-arm-kernel, linux-mediatek
In-Reply-To: <6a2b40e7.4dd82583.3a5c46.e566@mx.google.com>
[-- Attachment #1: Type: text/plain, Size: 1499 bytes --]
> In airoha_qdma_init_qos_stats(), the Tx-fwd counter configuration
> register uses the same index (i << 1) as the Tx-cpu counter, which
> overwrites the Tx-cpu configuration. The Tx-fwd counter value register
> correctly uses (i << 1) + 1, so the configuration register should use
> the same index.
>
> Fix the REG_CNTR_CFG index from (i << 1) to ((i << 1) + 1) so that
> the Tx-fwd counter is properly configured instead of clobbering the
> Tx-cpu counter config.
>
> Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
> Signed-off-by: Wayen.Yan <win847@gmail.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 31cdb11..329988a 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1256,7 +1256,7 @@ static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
> FIELD_PREP(CNTR_CHAN_MASK, i));
> /* Tx-fwd transferred count */
> airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
> - airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
> + airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1),
> CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
> CNTR_ALL_DSCP_RING_EN_MASK |
> FIELD_PREP(CNTR_SRC_MASK, 1) |
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v2] net: airoha: Add TCP LRO support
From: Lorenzo Bianconi @ 2026-06-12 10:05 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, linux-arm-kernel, linux-mediatek, netdev,
Madhur Agrawal
In-Reply-To: <20260610-airoha-eth-lro-v2-1-54be99b9a2d5@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 16917 bytes --]
> Add hardware TCP Large Receive Offload (LRO) support to the airoha_eth
> driver, leveraging the EN7581/AN7583 SoC's 8 dedicated LRO hardware queues
> mapped to RX queues 24–31. LRO hw offloading does not support
> Scatter-Gather (SG) so it is required to increase the page_pool allocation
> order to 2 for RX queues 24–31 (LRO queues).
> Since HW LRO is configured per-QDMA and shared across all devices using
> it, LRO is mutually exclusive with multiple active devices on the same
> QDMA block. Call netdev_update_features() on sibling devices in
> ndo_open/ndo_stop so that NETIF_F_LRO availability is re-evaluated when
> the QDMA user count changes.
>
> Performance comparison between GRO and hw LRO has been carried out using
> a 10Gbps NIC:
> GRO: ~2.7 Gbps
> LRO: ~8.1 Gbps
>
> Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
commenting on sashiko's report:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260610-airoha-eth-lro-v2-1-54be99b9a2d5%40kernel.org
[...]
>
> +static int airoha_qdma_lro_rx_process(struct sk_buff *skb,
> + struct airoha_qdma_desc *desc)
> +{
> + u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
> + u32 len, th_off, tcp_ack_seq, agg_count, data_off;
> + struct skb_shared_info *shinfo = skb_shinfo(skb);
> + u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1));
> + u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2));
> + u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3));
> + u16 tcp_win, l2_len;
> + struct tcphdr *th;
> + bool ipv4, ipv6;
> +
> + agg_count = FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2);
> + if (agg_count <= 1)
> + return 0;
> +
> + ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1);
> + ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1);
> + if (!ipv4 && !ipv6)
> + return -EOPNOTSUPP;
> +
> + l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2);
> + len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
> + if (ipv4) {
> + struct iphdr *iph, _iph;
> +
> + iph = skb_header_pointer(skb, l2_len, sizeof(*iph), &_iph);
> + if (!iph)
> + return -EINVAL;
> +
> + if (iph->protocol != IPPROTO_TCP)
> + return -EOPNOTSUPP;
> +
> + if (iph->ihl < 5)
> + return -EINVAL;
> +
> + th_off = l2_len + (iph->ihl << 2);
> + if (!pskb_may_pull(skb, th_off))
> + return -EINVAL;
> +
> + iph = (struct iphdr *)(skb->data + l2_len);
> + iph->tot_len = cpu_to_be16(len - l2_len);
> + iph->check = 0;
> + iph->check = ip_fast_csum((void *)iph, iph->ihl);
> + } else {
> + struct ipv6hdr *ip6h;
> +
> + th_off = l2_len + sizeof(*ip6h);
> + if (!pskb_may_pull(skb, th_off))
> + return -EINVAL;
> +
> + ip6h = (struct ipv6hdr *)(skb->data + l2_len);
> + if (ip6h->nexthdr != NEXTHDR_TCP)
> + return -EOPNOTSUPP;
> +
> + ip6h->payload_len = cpu_to_be16(len - th_off);
> + }
- The IPv6 path only checks ip6h->nexthdr != NEXTHDR_TCP and does not walk
extension headers (HBH, Routing, Fragment, Destination Options).
Can this misclassify any IPv6 packet that the HW happens to mark with
agg_count > 1 and includes extension headers?
- AFAIK the hw does not aggregate IPv6 packets with extensions headers
- Similarly, the IPv4 path does not consult QDMA_ETH_RXMSG_IP4F_MASK, so
IPv4 fragments that the HW reports as aggregated would also fall through
the protocol check.
- AFAIK the hw does not aggregate IPv4 fragments
- A related observation: this routine is invoked unconditionally for every
RX packet from airoha_qdma_rx_process(), with no airoha_qdma_is_lro_queue(q)
gate. Should non-LRO RX queues skip this entirely so that HW corner
cases on those queues cannot accidentally take this path?
- LRO will just return agg_count = 1 for non LRO queues.
> +
> + tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3);
> + tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data));
> +
> + if (!pskb_may_pull(skb, th_off + sizeof(*th)))
> + return -EINVAL;
> +
> + th = (struct tcphdr *)(skb->data + th_off);
> + data_off = th_off + (th->doff << 2);
> + if (len <= data_off)
> + return -EINVAL;
> +
> + th->ack_seq = cpu_to_be32(tcp_ack_seq);
> + th->window = cpu_to_be16(tcp_win);
> +
> + /* Check tcp timestamp option */
> + if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) {
> + u32 topt;
> +
> + if (!pskb_may_pull(skb, data_off))
> + return -EINVAL;
> +
> + th = (struct tcphdr *)(skb->data + th_off);
> + topt = get_unaligned_be32(th + 1);
> + if (topt == ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
> + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
> + u8 *ptr = (u8 *)th + sizeof(*th) + 2 * sizeof(__be32);
> + __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply);
> +
> + put_unaligned_be32(le32_to_cpu(tcp_ts_reply), ptr);
> + }
> + }
- Is the timestamp echo-reply refresh intentionally limited to the exact
doff == 8 case (12 bytes of options consisting of NOP/NOP/Timestamp)?
- AFAIU HW LRO can only aggregate TCP segments that belong to the same flow
and have the same TCP option layout across all segments.
The HW can't aggregate segments with variable layout (e.g. SACK) and they
will reported with agg_count sets to 1.
> +
> + shinfo->gso_type = ipv4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
> + shinfo->gso_size = (len - data_off) / agg_count;
> + shinfo->gso_segs = agg_count;
> +
> + return 0;
> +}
> +
> static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> {
> enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
> @@ -694,9 +836,17 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> __skb_put(q->skb, len);
> skb_mark_for_recycle(q->skb);
> q->skb->dev = netdev;
> - q->skb->protocol = eth_type_trans(q->skb, netdev);
> q->skb->ip_summed = CHECKSUM_UNNECESSARY;
> skb_record_rx_queue(q->skb, qid);
> +
> + if (airoha_qdma_lro_rx_process(q->skb, desc) < 0) {
> + netdev->stats.rx_dropped++;
> + dev_kfree_skb(q->skb);
> + q->skb = NULL;
> + continue;
> + }
- On a non-zero return from airoha_qdma_lro_rx_process(), this drops the
entire packet and bumps rx_dropped. Several of the early returns are
-EOPNOTSUPP for "this packet is not plain TCPv4/TCPv6", which previously
would have been delivered up the stack normally.
Would treating -EOPNOTSUPP as "deliver without GSO marking" be safer
than dropping? Otherwise any HW corner case that sets agg_count > 1
on a non-TCP packet becomes a silent drop visible only as rx_dropped.
- This is not doable since the hardware has already merged multiple packets
into one, the payload contains data from multiple original segments and
headers have been rewritten.
- A second concern in the same path: on non-LRO scatter-gather queues,
if a multi-fragment packet's first buffer is dropped here, q->skb is
left NULL and the next descriptor's buffer enters the "first buffer"
branch even though it is actually a continuation fragment. Can this
lead to the next fragment being treated as a new packet head?
- This has not been introduced by this patch.
> +
> + q->skb->protocol = eth_type_trans(q->skb, netdev);
[...]
> +static void airoha_update_netdev_features(struct airoha_gdm_dev *dev)
> +{
> + struct airoha_eth *eth = dev->eth;
> + int i, j;
> +
> + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> + struct airoha_gdm_port *port = eth->ports[i];
> +
> + if (!port)
> + continue;
> +
> + for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
> + struct airoha_gdm_dev *iter_dev = port->devs[j];
> + struct net_device *netdev;
> +
> + if (!iter_dev || iter_dev == dev)
> + continue;
> +
> + if (iter_dev->qdma != dev->qdma)
> + continue;
> +
> + netdev = netdev_from_priv(iter_dev);
> + if (netdev->reg_state != NETREG_REGISTERED)
> + continue;
> +
> + netdev_update_features(netdev);
> + }
> + }
> +}
> +
> static int airoha_dev_open(struct net_device *netdev)
> {
> int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN;
> @@ -1778,6 +1970,18 @@ static int airoha_dev_open(struct net_device *netdev)
> struct airoha_gdm_port *port = dev->port;
> u32 cur_len, pse_port = FE_PSE_PORT_PPE1;
> struct airoha_qdma *qdma = dev->qdma;
> + int qdma_id = qdma - &qdma->eth->qdma[0];
> +
> + /* HW LRO is configured on the QDMA and it is shared between
> + * all the devices using it. Refuse to open a second device on
> + * the same QDMA if LRO is enabled on any device sharing it.
> + */
> + if (atomic_read(&qdma->users) &&
> + airoha_fe_lro_is_enabled(qdma->eth, qdma_id)) {
> + netdev_warn(netdev, "required to disable LRO on QDMA%d\n",
> + qdma_id);
> + return -EBUSY;
> + }
- Consider this sequence on a single QDMA:
1. devA opens, devA enables NETIF_F_LRO via ethtool
-> airoha_fe_lro_init_rx_queue() programs REG_CDM_LRO_EN
2. devA closes -> airoha_dev_stop() runs
airoha_dev_stop() does not call airoha_fe_lro_disable() when
atomic_dec_and_test(&qdma->users) succeeds, so REG_CDM_LRO_EN bits
remain set in HW after the last user goes away.
3. devB opens on the same QDMA
The guard above evaluates atomic_read(&qdma->users) == 0 first, so the
EBUSY branch is short-circuited and devB opens successfully even though
the HW is still in LRO mode. devB will then receive HW-aggregated GSO
packets despite NETIF_F_LRO not being set on its features.
4. devA tries to reopen
Now atomic_read(&qdma->users) == 1 and airoha_fe_lro_is_enabled() still
returns true, so devA gets EBUSY even though the only "LRO user" is
stale HW state from its previous incarnation.
Should airoha_dev_stop() call airoha_fe_lro_disable() when the QDMA
user count drops to zero, or should the open path reset stale LRO state
when users == 0?
- This issue is valid and I will fix in the next revision.
>
> netif_tx_start_all_queues(netdev);
> err = airoha_set_vip_for_gdm_port(dev, true);
> @@ -1817,6 +2021,8 @@ static int airoha_dev_open(struct net_device *netdev)
> airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
> pse_port);
>
> + airoha_update_netdev_features(dev);
> +
> return 0;
> }
>
> @@ -1876,6 +2082,8 @@ static int airoha_dev_stop(struct net_device *netdev)
> }
> }
>
> + airoha_update_netdev_features(dev);
> +
> return 0;
> }
>
> @@ -2154,6 +2362,56 @@ int airoha_get_fe_port(struct airoha_gdm_dev *dev)
> }
> }
>
> +static netdev_features_t airoha_dev_fix_features(struct net_device *netdev,
> + netdev_features_t features)
> +{
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_qdma *qdma = dev->qdma;
> +
> + if (atomic_read(&qdma->users) > 1)
> + features &= ~NETIF_F_LRO;
> +
> + return features;
> +}
> +
> +static int airoha_dev_set_features(struct net_device *netdev,
> + netdev_features_t features)
> +{
> + netdev_features_t diff = netdev->features ^ features;
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_qdma *qdma = dev->qdma;
> + struct airoha_eth *eth = qdma->eth;
> + int qdma_id = qdma - ð->qdma[0];
> +
> + if (!(diff & NETIF_F_LRO))
> + return 0;
> +
> + if (features & NETIF_F_LRO) {
> + int i, lro_queue_index = 0;
> +
> + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
> + struct airoha_queue *q = &qdma->q_rx[i];
> + u32 size;
> +
> + if (!q->ndesc)
> + continue;
> +
> + if (!airoha_qdma_is_lro_queue(q))
> + continue;
> +
> + size = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
> + size = min_t(u32, size, CDM_LRO_AGG_SIZE_MASK);
> + airoha_fe_lro_init_rx_queue(eth, qdma_id,
> + lro_queue_index, i, size);
> + lro_queue_index++;
> + }
> + } else {
> + airoha_fe_lro_disable(eth, qdma_id);
> + }
> +
> + return 0;
> +}
> +
> static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> struct net_device *netdev)
> {
> @@ -3082,6 +3340,8 @@ static const struct net_device_ops airoha_netdev_ops = {
> .ndo_stop = airoha_dev_stop,
> .ndo_change_mtu = airoha_dev_change_mtu,
> .ndo_select_queue = airoha_dev_select_queue,
> + .ndo_fix_features = airoha_dev_fix_features,
> + .ndo_set_features = airoha_dev_set_features,
> .ndo_start_xmit = airoha_dev_xmit,
> .ndo_get_stats64 = airoha_dev_get_stats64,
> .ndo_set_mac_address = airoha_dev_set_macaddr,
> @@ -3169,11 +3429,9 @@ static int airoha_alloc_gdm_device(struct airoha_eth *eth,
> netdev->ethtool_ops = &airoha_ethtool_ops;
> netdev->max_mtu = AIROHA_MAX_MTU;
> netdev->watchdog_timeo = 5 * HZ;
> - netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 |
> - NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO |
> - NETIF_F_HW_TC;
> - netdev->features |= netdev->hw_features;
> - netdev->vlan_features = netdev->hw_features;
> + netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO;
> + netdev->features |= AIROHA_HW_FEATURES;
> + netdev->vlan_features = AIROHA_HW_FEATURES;
> SET_NETDEV_DEV(netdev, eth->dev);
- Is NETIF_F_LRO the right feature flag here?
- I guess it is ok to use NETIF_F_GRO_HW here. I will work on it.
Regards,
Lorenzo
>
> /* reserve hw queues for HTB offloading */
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 8f42973f9cf5..e78ef751f244 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -44,6 +44,18 @@
> (_n) == 15 ? 128 : \
> (_n) == 0 ? 1024 : 16)
>
> +#define AIROHA_LRO_PAGE_ORDER order_base_2(SZ_16K / PAGE_SIZE)
> +#define AIROHA_MAX_NUM_LRO_QUEUES 8
> +#define AIROHA_RXQ_LRO_EN_MASK GENMASK(31, 24)
> +#define AIROHA_RXQ_LRO_MAX_AGG_COUNT 64
> +#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100
> +#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000
> +
> +#define AIROHA_HW_FEATURES \
> + (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \
> + NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \
> + NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC)
> +
> #define PSE_RSV_PAGES 128
> #define PSE_QUEUE_RSV_PAGES 64
>
> @@ -672,6 +684,18 @@ static inline bool airoha_is_7583(struct airoha_eth *eth)
> return eth->soc->version == 0x7583;
> }
>
> +static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q)
> +{
> + struct airoha_qdma *qdma = q->qdma;
> + int qid = q - &qdma->q_rx[0];
> +
> + /* EN7581 SoC supports at most 8 LRO rx queues */
> + BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) >
> + AIROHA_MAX_NUM_LRO_QUEUES);
> +
> + return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid));
> +}
> +
> int airoha_get_fe_port(struct airoha_gdm_dev *dev);
> bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
> struct airoha_gdm_dev *dev);
> diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
> index 436f3c8779c1..dfc786583774 100644
> --- a/drivers/net/ethernet/airoha/airoha_regs.h
> +++ b/drivers/net/ethernet/airoha/airoha_regs.h
> @@ -122,6 +122,20 @@
> #define CDM_CRSN_QSEL_REASON_MASK(_n) \
> GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3))
>
> +#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4))
> +#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3)
> +
> +#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80)
> +#define LRO_RXQ_EN_MASK GENMASK(7, 0)
> +
> +#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84)
> +#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16)
> +#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0)
> +
> +#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88)
> +#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16)
> +#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0)
> +
> #define REG_GDM_FWD_CFG(_n) GDM_BASE(_n)
> #define GDM_PAD_EN_MASK BIT(28)
> #define GDM_DROP_CRC_ERR_MASK BIT(23)
> @@ -883,9 +897,15 @@
> #define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21)
> #define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16)
> #define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0)
> +/* RX MSG2 */
> +#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24)
> +#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0)
> +/* RX MSG3 */
> +#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16)
> +#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0)
>
> struct airoha_qdma_desc {
> - __le32 rsv;
> + __le32 tcp_ts_reply;
> __le32 ctrl;
> __le32 addr;
> __le32 data;
>
> ---
> base-commit: 660a9e399ab02c0cb86d277ed6b0c9d10c350fdd
> change-id: 20260520-airoha-eth-lro-a5d1c3631811
>
> Best regards,
> --
> Lorenzo Bianconi <lorenzo@kernel.org>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
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