Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 03/10] devfreq: Add a dedicated mutex for the governor list
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
  To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
  Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
	zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>

Accessing the list of available governors ('devfreq_governor_list') is
currently guarded by 'devfreq_list_lock', but 'devfreq_list_lock' is
supposed to protect the list of devfreq devices ('devfreq_list').

The scope of 'devfreq_list_lock' is too broad to maintain.
'devfreq_governor_list' should have its own mutex lock rather than share
with 'devfreq_list'.

Add a governor mutex lock and lock it when accessing the governor list.
Remove locking of 'devfreq_list_lock' around 'devfreq_governor_list'.

This is also a preparation for further refactoring around
try_then_request_governor().

Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
 drivers/devfreq/devfreq.c | 31 +++++++++++++------------------
 1 file changed, 13 insertions(+), 18 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 83f75dc21c99..e54e3092e0e0 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -49,6 +49,7 @@ static struct workqueue_struct *devfreq_wq;
 
 /* The list of all device-devfreq governors */
 static LIST_HEAD(devfreq_governor_list);
+static DEFINE_MUTEX(devfreq_gov_lock);
 /* The list of all device-devfreq */
 static LIST_HEAD(devfreq_list);
 static DEFINE_MUTEX(devfreq_list_lock);
@@ -255,19 +256,18 @@ EXPORT_SYMBOL(devfreq_update_status);
  * @name:	name of the governor
  *
  * Search the list of devfreq governors and return the matched
- * governor's pointer. devfreq_list_lock should be held by the caller.
+ * governor's pointer.
  */
 static struct devfreq_governor *find_devfreq_governor(const char *name)
 {
 	struct devfreq_governor *tmp_governor;
 
-	lockdep_assert_held(&devfreq_list_lock);
-
 	if (IS_ERR_OR_NULL(name)) {
 		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
 		return ERR_PTR(-EINVAL);
 	}
 
+	guard(mutex)(&devfreq_gov_lock);
 	list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
 		if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
 			return tmp_governor;
@@ -284,16 +284,13 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
  * Search the list of devfreq governors and request the module and try again
  * if is not found. This can happen when both drivers (the governor driver
  * and the driver that call devfreq_add_device) are built as modules.
- * devfreq_list_lock should be held by the caller. Returns the matched
- * governor's pointer or an error pointer.
+ * Returns the matched governor's pointer or an error pointer.
  */
 static struct devfreq_governor *try_then_request_governor(const char *name)
 {
 	struct devfreq_governor *governor;
 	int err = 0;
 
-	lockdep_assert_held(&devfreq_list_lock);
-
 	if (IS_ERR_OR_NULL(name)) {
 		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
 		return ERR_PTR(-EINVAL);
@@ -301,15 +298,12 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
 
 	governor = find_devfreq_governor(name);
 	if (IS_ERR(governor)) {
-		mutex_unlock(&devfreq_list_lock);
-
 		if (!strncmp(name, DEVFREQ_GOV_SIMPLE_ONDEMAND,
 			     DEVFREQ_NAME_LEN))
 			err = request_module("governor_%s", "simpleondemand");
 		else
 			err = request_module("governor_%s", name);
 		/* Restore previous state before return */
-		mutex_lock(&devfreq_list_lock);
 		if (err)
 			return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
 
@@ -933,16 +927,15 @@ struct devfreq *devfreq_add_device(struct device *dev,
 	if (err)
 		goto err_devfreq;
 
-	mutex_lock(&devfreq_list_lock);
-
 	governor = try_then_request_governor(governor_name);
 	if (IS_ERR(governor)) {
 		dev_err(dev, "%s: Unable to find governor for the device\n",
 			__func__);
 		err = PTR_ERR(governor);
-		goto err_init;
+		goto err_devfreq;
 	}
 
+	mutex_lock(&devfreq_list_lock);
 	devfreq->governor = governor;
 	err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
 						NULL);
@@ -1269,7 +1262,6 @@ int devfreq_add_governor(struct devfreq_governor *governor)
 		return -EINVAL;
 	}
 
-	guard(mutex)(&devfreq_list_lock);
 	g = find_devfreq_governor(governor->name);
 	if (!IS_ERR(g)) {
 		pr_err("%s: governor %s already registered\n", __func__,
@@ -1277,8 +1269,10 @@ int devfreq_add_governor(struct devfreq_governor *governor)
 		return -EINVAL;
 	}
 
-	list_add(&governor->node, &devfreq_governor_list);
+	scoped_guard(mutex, &devfreq_gov_lock)
+		list_add(&governor->node, &devfreq_governor_list);
 
+	guard(mutex)(&devfreq_list_lock);
 	list_for_each_entry(devfreq, &devfreq_list, node) {
 		int ret = 0;
 		struct device *dev = devfreq->dev.parent;
@@ -1355,7 +1349,6 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
 		return -EINVAL;
 	}
 
-	guard(mutex)(&devfreq_list_lock);
 	g = find_devfreq_governor(governor->name);
 	if (IS_ERR(g)) {
 		pr_err("%s: governor %s not registered\n", __func__,
@@ -1363,6 +1356,7 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
 		return PTR_ERR(g);
 	}
 
+	guard(mutex)(&devfreq_list_lock);
 	list_for_each_entry(devfreq, &devfreq_list, node) {
 		int ret;
 		struct device *dev = devfreq->dev.parent;
@@ -1383,7 +1377,8 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
 		}
 	}
 
-	list_del(&governor->node);
+	scoped_guard(mutex, &devfreq_gov_lock)
+		list_del(&governor->node);
 
 	return 0;
 }
@@ -1423,11 +1418,11 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
 	if (ret != 1)
 		return -EINVAL;
 
-	guard(mutex)(&devfreq_list_lock);
 	governor = try_then_request_governor(str_governor);
 	if (IS_ERR(governor))
 		return PTR_ERR(governor);
 
+	guard(mutex)(&devfreq_list_lock);
 	if (df->governor == governor)
 		return count;
 
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 10/10] devfreq: Allow setting governor when device governor is NULL
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
  To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
  Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
	zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>

From: Zhi Wang <wangzhi12@huawei.com>

When a device's governor is set to NULL, the system should allow
reconfiguring the governor to restore normal operation of devfreq

Before:
$: echo simple_ondemand > governor
$: rmmod -f governor_simpleondemand
$: echo performance > governor
-bash: echo: write error: Invalid argument

After:
$: echo simple_ondemand > governor
$: rmmod -f governor_simpleondemand
$: echo performance > governor
$: cat governor
performance

Signed-off-by: Zhi Wang <wangzhi12@huawei.com>
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
 drivers/devfreq/devfreq.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 5aebb32e89b0..a61880ff2792 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1435,9 +1435,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
 	char str_governor[DEVFREQ_NAME_LEN + 1];
 	const struct devfreq_governor *governor;
 
-	if (!df->governor)
-		return -EINVAL;
-
 	ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
 	if (ret != 1)
 		return -EINVAL;
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH 3/3] pinctrl: mediatek: mt8901: Add pinctrl driver for MT8901
From: Fred-WY Chen (陳威宇) @ 2026-03-26 12:36 UTC (permalink / raw)
  To: Mandeep S, AngeloGioacchino Del Regno, Deep Pani,
	sean.wang@kernel.org, matthias.bgg@gmail.com,
	Lei Xue (薛磊), linus.walleij@linaro.org
  Cc: Qingliang Li (黎晴亮),
	Ye Wang (王叶), Yaoy Wang (王瑶瑶),
	linux-gpio@vger.kernel.org, Yong Mao (毛勇),
	Shunxi Zhang (章顺喜),
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Cathy Xu (许华婷)
In-Reply-To: <df11bbf1-09d1-40fc-be56-6a98d90abcb6@collabora.com>

On Tue, 2025-11-25 at 10:56 +0100, AngeloGioacchino Del Regno wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Il 25/11/25 03:36, Lei Xue ha scritto:
> > Add mt8901 pinctrl, gpio and eint driver implementation.
> > 
> > Signed-off-by: Lei Xue <lei.xue@mediatek.com>
> > ---
> >   drivers/pinctrl/mediatek/Kconfig              |   12 +
> >   drivers/pinctrl/mediatek/Makefile             |    1 +
> >   drivers/pinctrl/mediatek/mtk-eint.c           |    4 +
> >   drivers/pinctrl/mediatek/mtk-eint.h           |    1 +
> >   drivers/pinctrl/mediatek/pinctrl-mt8901.c     | 1460 +++++++++++
> >   drivers/pinctrl/mediatek/pinctrl-mtk-mt8901.h | 2130
> > +++++++++++++++++
> >   6 files changed, 3608 insertions(+)
> >   create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt8901.c
> >   create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt8901.h
> > 
> > diff --git a/drivers/pinctrl/mediatek/Kconfig
> > b/drivers/pinctrl/mediatek/Kconfig
> > index 4819617d9368..4820ae5197a0 100644
> > --- a/drivers/pinctrl/mediatek/Kconfig
> > +++ b/drivers/pinctrl/mediatek/Kconfig
> > @@ -321,6 +321,18 @@ config PINCTRL_MT8516
> >       default ARM64 && ARCH_MEDIATEK
> >       select PINCTRL_MTK
> > 
> > +config PINCTRL_MT8901
> > +     bool "MediaTek MT8901 pin control"
> > +     depends on ACPI
> > +     depends on ARM64 || COMPILE_TEST
> > +     default ARM64 && ARCH_MEDIATEK
> > +     select PINCTRL_MTK_PARIS
> > +     help
> > +       Say yes here to support pin controller and gpio driver
> > +       on MediaTek MT8901 SoC.
> > +       In MTK platform, we support virtual gpio and use it to
> > +       map specific eint which doesn't have real gpio pin.
> > +
> >   # For PMIC
> >   config PINCTRL_MT6397
> >       bool "MediaTek MT6397 pin control"
> > diff --git a/drivers/pinctrl/mediatek/Makefile
> > b/drivers/pinctrl/mediatek/Makefile
> > index ae765bd99965..57c69b1e5c2d 100644
> > --- a/drivers/pinctrl/mediatek/Makefile
> > +++ b/drivers/pinctrl/mediatek/Makefile
> > @@ -43,3 +43,4 @@ obj-$(CONFIG_PINCTRL_MT8196)                +=
> > pinctrl-mt8196.o
> >   obj-$(CONFIG_PINCTRL_MT8365)                += pinctrl-mt8365.o
> >   obj-$(CONFIG_PINCTRL_MT8516)                += pinctrl-mt8516.o
> >   obj-$(CONFIG_PINCTRL_MT6397)                += pinctrl-mt6397.o
> > +obj-$(CONFIG_PINCTRL_MT8901)         += pinctrl-mt8901.o
> > diff --git a/drivers/pinctrl/mediatek/mtk-eint.c
> > b/drivers/pinctrl/mediatek/mtk-eint.c
> > index c8c5097c11c4..b5a5beebf9cd 100644
> > --- a/drivers/pinctrl/mediatek/mtk-eint.c
> > +++ b/drivers/pinctrl/mediatek/mtk-eint.c
> > @@ -71,6 +71,10 @@ const unsigned int debounce_time_mt6878[] = {
> >   };
> >   EXPORT_SYMBOL_GPL(debounce_time_mt6878);
> > 
> > +const unsigned int debounce_time_mt8901[] = {
> > +     156, 313, 625, 1250, 20000, 40000, 80000, 160000, 320000,
> > 640000, 0};
> > +EXPORT_SYMBOL_GPL(debounce_time_mt8901);
> > +
> >   static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
> >                                        unsigned int eint_num,
> >                                        unsigned int offset)
> > diff --git a/drivers/pinctrl/mediatek/mtk-eint.h
> > b/drivers/pinctrl/mediatek/mtk-eint.h
> > index 3cdd6f6310cd..1b185f660aff 100644
> > --- a/drivers/pinctrl/mediatek/mtk-eint.h
> > +++ b/drivers/pinctrl/mediatek/mtk-eint.h
> > @@ -53,6 +53,7 @@ extern const unsigned int debounce_time_mt2701[];
> >   extern const unsigned int debounce_time_mt6765[];
> >   extern const unsigned int debounce_time_mt6795[];
> >   extern const unsigned int debounce_time_mt6878[];
> > +extern const unsigned int debounce_time_mt8901[];
> > 
> >   struct mtk_eint;
> > 
> > diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > b/drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > new file mode 100644
> > index 000000000000..77dec85fe29b
> > --- /dev/null
> > +++ b/drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > @@ -0,0 +1,1460 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2025 MediaTek Inc.
> > + *
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/module.h>
> > +#include "pinctrl-mtk-mt8901.h"
> > +#include "pinctrl-paris.h"
> > +
> 
> ..snip..
> 
> > +static const char * const mt8901_pinctrl_register_base_name[] = {
> > +     "iocfg0", "iocfg_lt2", "iocfg_lt3", "iocfg_rt1", "iocfg_rt2",
> > "iocfg_rt3",
> > +     "iocfg_tr", "iocfg_rt0", "iocfg_lt1", "iocfg_lb", "iocfg_rb",
> > +};
> > +
> > +static const struct mtk_eint_hw mt8901_eint_hw = {
> > +     .port_mask = 0xf,
> > +     .ports     = 7,
> > +     .ap_num    = 209,
> > +     .db_cnt    = 32,
> > +     .db_time   = debounce_time_mt8901,
> > +};
> > +
> > +static const struct mtk_pin_soc mt8901_data = {
> > +     .reg_cal = mt8901_reg_cals,
> > +     .pins = mtk_pins_mt8901,
> > +     .npins = ARRAY_SIZE(mtk_pins_mt8901),
> > +     .ngrps = ARRAY_SIZE(mtk_pins_mt8901),
> > +     .eint_hw = &mt8901_eint_hw,
> > +     .eint_pin = eint_pins_mt8901,
> > +     .nfuncs = 8,
> > +     .gpio_m = 0,
> > +     .base_names = mt8901_pinctrl_register_base_name,
> > +     .nbase_names = ARRAY_SIZE(mt8901_pinctrl_register_base_name),
> > +     .pull_type = mt8901_pull_type,
> > +     .pin_rsel = mt8901_pin_rsel_val_range,
> > +     .npin_rsel = ARRAY_SIZE(mt8901_pin_rsel_val_range),
> > /*numsel*/
> > +     .bias_set_combo = mtk_pinconf_bias_set_combo,
> > +     .bias_get_combo = mtk_pinconf_bias_get_combo,
> > +     .drive_set = mtk_pinconf_drive_set_rev1,
> > +     .drive_get = mtk_pinconf_drive_get_rev1,
> > +     .adv_drive_set = mtk_pinconf_adv_drive_set_raw,
> > +     .adv_drive_get = mtk_pinconf_adv_drive_get_raw,
> > +};
> > +
> > +static const struct acpi_device_id mt8901_pinctrl_acpi_match[] = {
> > +     {"NVDA9221", (kernel_ulong_t)&mt8901_data },
> > +     { }
> > +};
> > +MODULE_DEVICE_TABLE(acpi, mt8901_pinctrl_acpi_match);
> > +
> > +static struct platform_driver mt8901_pinctrl_driver = {
> > +     .driver = {
> > +             .name = "mt8901-pinctrl",
> > +             .acpi_match_table =
> > ACPI_PTR(mt8901_pinctrl_acpi_match),
> 
> Please also add support for devicetree - I have a hunch (and I'm sure
> that I am
> not the only one) that ACPI may give some issues at the end of the
> day, on ARM64.
> 
> Of course, I'd hope that ACPI is all good on this platform, but
> still.... :-)
> 
> static const struct of_device_id mt8901_pinctrl_of_match[] = {
>         { .compatible = "mediatek,mt8901-pinctrl", .data =
> &mt8901_data },
>         { /* sentinel */ }
> };
> 
>         .of_match_table = mt8901_pinctrl_of_match,
> 
> > +             .pm = pm_sleep_ptr(&mtk_paris_pinctrl_pm_ops)
> > +     },
> > +     .probe = mtk_paris_pinctrl_probe,
> > +};
> 

Hi Deep,

Could you please check and feedback to Angelo?

Regards,
Fred-WY Chen

> Cheers,
> Angelo
> 
> > +
> > +static int __init mt8901_pinctrl_init(void)
> > +{
> > +     return platform_driver_register(&mt8901_pinctrl_driver);
> > +}
> > +
> > +arch_initcall(mt8901_pinctrl_init);
> > +
> > +MODULE_LICENSE("GPL");
> > +MODULE_DESCRIPTION("MediaTek MT8901 Pinctrl Driver");


^ permalink raw reply

* Re: [PATCH RESEND] mmc: mtk-sd: disable new_tx/rx and modify related settings for mt8189
From: Ulf Hansson @ 2026-03-26 12:34 UTC (permalink / raw)
  To: Cathy Xu
  Cc: Chaotian Jing, Matthias Brugger, AngeloGioacchino Del Regno,
	Louis-Alexis Eyraud, linux-mmc, linux-kernel, linux-arm-kernel,
	linux-mediatek, Mengqi Zhang, Wenbin Mei, Andy-ld Lu, Axe Yang,
	Yong Mao, stable
In-Reply-To: <20260326030759.8107-1-ot_cathy.xu@mediatek.com>

On Thu, 26 Mar 2026 at 04:08, Cathy Xu <ot_cathy.xu@mediatek.com> wrote:
>
> Disable new_tx/rx to avoid data transmission instability, and adjust
> .data_tune, .stop_dly_sel, and .pop_en_cnt to fit the overall
> configuration after disabling new_tx/rx, making it more compatible
> with mt8189.
>
> Fixes: 846a3a2fdff5 ("mmc: mtk-sd: add support for MT8189 SoC")
> Cc: stable@vger.kernel.org
> Tested-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
> Signed-off-by: Cathy Xu <ot_cathy.xu@mediatek.com>

Applied for fixes and by dropping the stable-tag as it's superfluous
in this case. Thanks!

Kind regards
Uffe



> ---
>  drivers/mmc/host/mtk-sd.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 302ac8529c4f..b2680cc054bd 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -682,15 +682,15 @@ static const struct mtk_mmc_compatible mt8189_compat = {
>         .needs_top_base = true,
>         .pad_tune_reg = MSDC_PAD_TUNE0,
>         .async_fifo = true,
> -       .data_tune = true,
> +       .data_tune = false,
>         .busy_check = true,
>         .stop_clk_fix = true,
> -       .stop_dly_sel = 1,
> -       .pop_en_cnt = 2,
> +       .stop_dly_sel = 3,
> +       .pop_en_cnt = 8,
>         .enhance_rx = true,
>         .support_64g = true,
> -       .support_new_tx = true,
> -       .support_new_rx = true,
> +       .support_new_tx = false,
> +       .support_new_rx = false,
>         .support_spm_res_release = true,
>  };
>
> --
> 2.45.2
>


^ permalink raw reply

* Re: [PATCH v2 1/2] dt-bindings: mmc: hisilicon,hi3660-dw-mshc: Convert to DT schema
From: Ulf Hansson @ 2026-03-26 12:34 UTC (permalink / raw)
  To: Bhargav Joshi
  Cc: devicetree, linux-arm-kernel, xuwei5, robh, krzk+dt, conor+dt,
	zhangfei.gao, linux-mmc, daniel.baluta, simona.toaca, d-gole,
	m-chawdhry, linux-kernel
In-Reply-To: <20260325225439.68161-2-rougueprince47@gmail.com>

On Wed, 25 Mar 2026 at 23:55, Bhargav Joshi <rougueprince47@gmail.com> wrote:
>
> Convert the Hisilicon DesignWare Mobile Storage Host Controller
> (dw-mshc) bindings from text format to DT schema.
>
> As part of this conversion, the binding file is renamed from
> k3-dw-mshc.txt to hisilicon,hi3660-dw-mshc.yaml to align with compatible
> string naming conventions. Examples have been updated to pass schema
> validation.
>
> Note: synopsys-dw-mshc binding specifies clock names as "biu" followed
> by "ciu". However, this Hisilicon binding reverses the order to 'ciu'
> then 'biu' to match both the legacy text binding and in-kernel Hisilicon
> DTS board files.
>
> Signed-off-by: Bhargav Joshi <rougueprince47@gmail.com>
> Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>

Applied for next, thanks!

Kind regards
Uffe



> ---
> Changes in v2:
>     - Grouped compatible strings into an enum.
>     - Replaced raw numbers with proper flags.
>     - Fixed property order and removed invalid hex values.
>     - Added explanation for clock order change in commit message.
>     - Collected Acked-by tag.
>
>  .../mmc/hisilicon,hi3660-dw-mshc.yaml         | 117 ++++++++++++++++++
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt    |  73 -----------
>  2 files changed, 117 insertions(+), 73 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
>  delete mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>
> diff --git a/Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
> new file mode 100644
> index 000000000000..296bd776488e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
> @@ -0,0 +1,117 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mmc/hisilicon,hi3660-dw-mshc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Hisilicon specific extensions to the Synopsys Designware Mobile Storage Host Controller
> +
> +maintainers:
> +  - Zhangfei Gao <zhangfei.gao@linaro.org>
> +
> +description:
> +  The Synopsys designware mobile storage host controller is used to interface
> +  a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +  differences between the core Synopsys dw mshc controller properties described
> +  by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +  extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +allOf:
> +  - $ref: /schemas/mmc/synopsys-dw-mshc-common.yaml#
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - hisilicon,hi3660-dw-mshc
> +          - hisilicon,hi4511-dw-mshc
> +          - hisilicon,hi6220-dw-mshc
> +      - items:
> +          - const: hisilicon,hi3670-dw-mshc
> +          - const: hisilicon,hi3660-dw-mshc
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: card interface unit clock
> +      - description: bus interface unit clock
> +
> +  clock-names:
> +    items:
> +      - const: ciu
> +      - const: biu
> +
> +  hisilicon,peripheral-syscon:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle of syscon used to control peripheral.
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +  - clock-names
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/hi3620-clock.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    mmc@fcd03000 {
> +        compatible = "hisilicon,hi4511-dw-mshc";
> +        reg = <0xfcd03000 0x1000>;
> +        interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +        clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +        clock-names = "ciu", "biu";
> +        vmmc-supply = <&ldo12>;
> +        fifo-depth = <0x100>;
> +        pinctrl-names = "default";
> +        pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +        bus-width = <4>;
> +        disable-wp;
> +        cd-gpios = <&gpio10 3 GPIO_ACTIVE_HIGH>;
> +        cap-mmc-highspeed;
> +        cap-sd-highspeed;
> +    };
> +
> +  - |
> +    #include <dt-bindings/clock/hi6220-clock.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    soc {
> +      #address-cells = <2>;
> +      #size-cells = <2>;
> +
> +      mmc@f723e000 {
> +          compatible = "hisilicon,hi6220-dw-mshc";
> +          reg = <0x0 0xf723e000 0x0 0x1000>;
> +          interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
> +          clocks = <&clock_sys HI6220_MMC1_CIUCLK>,
> +                   <&clock_sys HI6220_MMC1_CLK>;
> +          clock-names = "ciu", "biu";
> +          bus-width = <4>;
> +          disable-wp;
> +          cap-sd-highspeed;
> +          sd-uhs-sdr12;
> +          sd-uhs-sdr25;
> +          card-detect-delay = <200>;
> +          hisilicon,peripheral-syscon = <&ao_ctrl>;
> +          cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
> +          pinctrl-names = "default", "idle";
> +          pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
> +          pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
> +          vqmmc-supply = <&ldo7>;
> +          vmmc-supply = <&ldo10>;
> +      };
> +    };
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> deleted file mode 100644
> index 36c4bea675d5..000000000000
> --- a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> +++ /dev/null
> @@ -1,73 +0,0 @@
> -* Hisilicon specific extensions to the Synopsys Designware Mobile
> -  Storage Host Controller
> -
> -Read synopsys-dw-mshc.txt for more details
> -
> -The Synopsys designware mobile storage host controller is used to interface
> -a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> -differences between the core Synopsys dw mshc controller properties described
> -by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> -extensions to the Synopsys Designware Mobile Storage Host Controller.
> -
> -Required Properties:
> -
> -* compatible: should be one of the following.
> -  - "hisilicon,hi3660-dw-mshc": for controllers with hi3660 specific extensions.
> -  - "hisilicon,hi3670-dw-mshc", "hisilicon,hi3660-dw-mshc": for controllers
> -     with hi3670 specific extensions.
> -  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extensions.
> -  - "hisilicon,hi6220-dw-mshc": for controllers with hi6220 specific extensions.
> -
> -Optional Properties:
> -- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
> -
> -Example:
> -
> -       /* for Hi3620 */
> -
> -       /* SoC portion */
> -       dwmmc_0: dwmmc0@fcd03000 {
> -               compatible = "hisilicon,hi4511-dw-mshc";
> -               reg = <0xfcd03000 0x1000>;
> -               interrupts = <0 16 4>;
> -               #address-cells = <1>;
> -               #size-cells = <0>;
> -               clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> -               clock-names = "ciu", "biu";
> -       };
> -
> -       /* Board portion */
> -       dwmmc0@fcd03000 {
> -               vmmc-supply = <&ldo12>;
> -               fifo-depth = <0x100>;
> -               pinctrl-names = "default";
> -               pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> -               bus-width = <4>;
> -               disable-wp;
> -               cd-gpios = <&gpio10 3 0>;
> -               cap-mmc-highspeed;
> -               cap-sd-highspeed;
> -       };
> -
> -       /* for Hi6220 */
> -
> -       dwmmc_1: dwmmc1@f723e000 {
> -               compatible = "hisilicon,hi6220-dw-mshc";
> -               bus-width = <0x4>;
> -               disable-wp;
> -               cap-sd-highspeed;
> -               sd-uhs-sdr12;
> -               sd-uhs-sdr25;
> -               card-detect-delay = <200>;
> -               hisilicon,peripheral-syscon = <&ao_ctrl>;
> -               reg = <0x0 0xf723e000 0x0 0x1000>;
> -               interrupts = <0x0 0x49 0x4>;
> -               clocks = <&clock_sys HI6220_MMC1_CIUCLK>, <&clock_sys HI6220_MMC1_CLK>;
> -               clock-names = "ciu", "biu";
> -               cd-gpios = <&gpio1 0 1>;
> -               pinctrl-names = "default", "idle";
> -               pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
> -               pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
> -               vqmmc-supply = <&ldo7>;
> -               vmmc-supply = <&ldo10>;
> -       };
> --
> 2.53.0
>


^ permalink raw reply

* Re: [PATCH v5 2/9] dt-bindings: mmc: amlogic: Add compatible for T7 mmc
From: Ulf Hansson @ 2026-03-26 12:33 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Johannes Berg,
	van Spriel, linux-arm-kernel, linux-amlogic, devicetree,
	linux-kernel, linux-mmc, linux-wireless, Conor Dooley,
	Xianwei Zhao
In-Reply-To: <20260326-add-emmc-t7-vim4-v5-2-d3f182b48e9d@aliel.fr>

On Thu, 26 Mar 2026 at 11:01, Ronald Claveau <linux-kernel-dev@aliel.fr> wrote:
>
> Add amlogic,t7-mmc compatible string, falling back to amlogic,meson-axg-mmc
> as the T7 MMC controller is compatible with the AXG implementation.
>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Acked-by: Rob Herring (Arm) <robh@kernel.org>
> Reviewed-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
> index 57646575a13f8..976f36de2091c 100644
> --- a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
> @@ -19,6 +19,10 @@ allOf:
>  properties:
>    compatible:
>      oneOf:
> +      - items:
> +          - enum:
> +              - amlogic,t7-mmc
> +          - const: amlogic,meson-axg-mmc
>        - const: amlogic,meson-axg-mmc
>        - items:
>            - const: amlogic,meson-gx-mmc
>
> --
> 2.49.0
>


^ permalink raw reply

* Re: [PATCH v2 09/12] arm64: dts: imx8mp-sr-som: Correct PAD settings for PMIC_nINT
From: Josua Mayer @ 2026-03-26 12:33 UTC (permalink / raw)
  To: Peng Fan, Laurent Pinchart, Peng Fan (OSS)
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Shawn Guo,
	Daniel Scally, Marco Felsch, Gilles Talis, Viorel Suman,
	S.J. Wang, Jagan Teki, Manoj Sai, matteo.lisi, Ray Chang,
	Richard Hu, Heiko Schocher, Martyn Welch,
	Goran Rađenović, Börge Strümpfel,
	Christoph Niedermaier, Marek Vasut, devicetree@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, kernel@dh-electronics.com
In-Reply-To: <PAXPR04MB845972866AB6A7E85D1570CB8856A@PAXPR04MB8459.eurprd04.prod.outlook.com>

Hi Peng,

Am 26.03.26 um 10:55 schrieb Peng Fan:
>> Subject: Re: [PATCH v2 09/12] arm64: dts: imx8mp-sr-som: Correct
>> PAD settings for PMIC_nINT
>>> --- a/arch/arm64/boot/dts/freescale/imx8mp-sr-som.dtsi
>>> +++ b/arch/arm64/boot/dts/freescale/imx8mp-sr-som.dtsi
>>> @@ -174,7 +174,7 @@ pmic: pmic@25 {
>>>  		pinctrl-0 = <&pmic_pins>;
>>>  		pinctrl-names = "default";
>>>  		interrupt-parent = <&gpio1>;
>>> -		interrupts = <3 GPIO_ACTIVE_LOW>;
>>> +		interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
>> This is a good change, but it should be mentioned in the commit
>> message, or split to a separate patch. Same for other patches in this
>> series where you make the same change.
> Thanks, waiting to see if any board owners would give a test.
> Then I will update in V3.
>
> Thanks,
> Peng.

Looks correct to me.

Reviewed-by: Josua Mayer <josua@solid-run.com>

^ permalink raw reply

* Re: [PATCH 1/3] pinctrl: mediatek: Add gpio-range record in pinctrl driver
From: Fred-WY Chen (陳威宇) @ 2026-03-26 12:33 UTC (permalink / raw)
  To: andriy.shevchenko@intel.com, Deep Pani,
	Lei Xue (薛磊), Mandeep S
  Cc: Yong Mao (毛勇), sean.wang@kernel.org,
	Qingliang Li (黎晴亮),
	Yaoy Wang (王瑶瑶), AngeloGioacchino Del Regno,
	linux-gpio@vger.kernel.org, linus.walleij@linaro.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Cathy Xu (许华婷),
	linux-mediatek@lists.infradead.org, matthias.bgg@gmail.com,
	Ye Wang (王叶),
	Shunxi Zhang (章顺喜)
In-Reply-To: <aSdBt937C6Cjj_8s@black.igk.intel.com>

On Wed, 2025-11-26 at 19:06 +0100, Andy Shevchenko wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Tue, Nov 25, 2025 at 10:36:34AM +0800, Lei Xue wrote:
> > Kernel GPIO subsystem mapping hardware pin number to a different
> > range of gpio number. Add gpio-range structure to hold
> > the mapped gpio range in pinctrl driver. That enables the kernel
> > to search a range of mapped gpio range against a pinctrl device.
> 
> ...
> 
> >  static int mtk_build_gpiochip(struct mtk_pinctrl *hw)
> >  {
> >       struct gpio_chip *chip = &hw->chip;
> 
> >       if (ret < 0)
> >               return ret;
> > 
> > +     mtk_pinctrl_gpio_range_init(hw, chip);
> > +
> >       return 0;
> 
> We have a callback for that in struct gpio_chip. Any reason not to
> use it?
> 
> >  }
> 
> ...
> 
> > +     pinctrl_add_gpio_range(hw->pctrl, &hw->range);
> 
> Not sure if this is needed.
> 

Hi Deep,

Could you please check this and feedback?

Regards,
Fred-WY Chen

> --
> With Best Regards,
> Andy Shevchenko
> 
> 


^ permalink raw reply

* Re: [PATCH net-next v2 3/4] net: phy: air_phy_lib: Factorize BuckPBus register accessors
From: Andrew Lunn @ 2026-03-26 12:30 UTC (permalink / raw)
  To: Louis-Alexis Eyraud
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Heiner Kallweit, Russell King,
	kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <20260326-add-airoha-an8801-support-v2-3-1a42d6b6050f@collabora.com>

> @@ -480,8 +287,8 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev)
>  {
>  	int ret, reg_value;
>  
> -	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
> -				     EN8811H_FW_CTRL_1_FINISH);
> +	ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
> +					 EN8811H_FW_CTRL_1_FINISH);

Is a rename required? Is the namespace air_buckpbus_ used somewhere
else?

	Andrew


^ permalink raw reply

* Re: [PATCH v6 1/5] mm: rmap: support batched checks of the references for large folios
From: Lorenzo Stoakes (Oracle) @ 2026-03-26 12:21 UTC (permalink / raw)
  To: Baolin Wang
  Cc: David Hildenbrand (Arm), Barry Song, akpm, catalin.marinas, will,
	lorenzo.stoakes, ryan.roberts, Liam.Howlett, vbabka, rppt, surenb,
	mhocko, riel, harry.yoo, jannh, willy, dev.jain, linux-mm,
	linux-arm-kernel, linux-kernel
In-Reply-To: <aef474b9-5286-46f4-99d2-43d0b85f7176@linux.alibaba.com>

On Thu, Mar 26, 2026 at 08:04:10PM +0800, Baolin Wang wrote:
>
>
> On 3/26/26 7:10 PM, Lorenzo Stoakes (Oracle) wrote:
> > On Thu, Mar 26, 2026 at 09:47:51AM +0800, Baolin Wang wrote:
> > >
> > >
> > > On 3/25/26 11:06 PM, Lorenzo Stoakes (Oracle) wrote:
> > > > On Wed, Mar 25, 2026 at 03:58:36PM +0100, David Hildenbrand (Arm) wrote:
> > > > > On 3/25/26 15:36, Lorenzo Stoakes (Oracle) wrote:
> > > > > > On Mon, Mar 16, 2026 at 03:15:18PM +0100, David Hildenbrand (Arm) wrote:
> > > > > > > On 3/16/26 07:25, Baolin Wang wrote:
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > Sure. However, after investigating RISC‑V and x86, I found that
> > > > > > > > ptep_clear_flush_young() does not flush the TLB on these architectures:
> > > > > > > >
> > > > > > > > int ptep_clear_flush_young(struct vm_area_struct *vma,
> > > > > > > >                  unsigned long address, pte_t *ptep)
> > > > > > > > {
> > > > > > > >       /*
> > > > > > > >        * On x86 CPUs, clearing the accessed bit without a TLB flush
> > > > > > > >        * doesn't cause data corruption. [ It could cause incorrect
> > > > > > > >        * page aging and the (mistaken) reclaim of hot pages, but the
> > > > > > > >        * chance of that should be relatively low. ]
> > > > > > > >        *
> > > > > > > >        * So as a performance optimization don't flush the TLB when
> > > > > > > >        * clearing the accessed bit, it will eventually be flushed by
> > > > > > > >        * a context switch or a VM operation anyway. [ In the rare
> > > > > > > >        * event of it not getting flushed for a long time the delay
> > > > > > > >        * shouldn't really matter because there's no real memory
> > > > > > > >        * pressure for swapout to react to. ]
> > > > > > > >        */
> > > > > > > >       return ptep_test_and_clear_young(vma, address, ptep);
> > > > > > > > }
> > > > > > >
> > > > > > > You'd probably want an arch helper then, that tells you whether
> > > > > > > a flush_tlb_range() after ptep_test_and_clear_young() is required.
> > > > > > >
> > > > > > > Or some special flush_tlb_range() helper.
> > > > > > >
> > > > > > > I agree that it requires more work.
> > >
> > > (Sorry, David. I forgot to reply to your email because I've had a lot to
> > > sort out recently.)
> > >
> > > Rather than adding more arch helpers (we already have plenty for the young
> > > flag check), I think we should try removing the TLB flush, as I mentioned to
> > > Barry[1]. MGLRU reclaim already skips the TLB flush, and it seems to work
> > > fine. What do you think?
> > >
> > > Here are our previous attempts to remove the TLB flush:
> > >
> > > My patch: https://lkml.org/lkml/2023/10/24/533
> > > Barry's patch:
> > > https://lore.kernel.org/lkml/20220617070555.344368-1-21cnbao@gmail.com/
> > >
> > > [1] https://lore.kernel.org/all/6bdc4b03-9631-4717-a3fa-2785a7930aba@linux.alibaba.com/
> > >
> > > > > > Sorry unclear here - does the series need more work or does a follow up patch
> > > > > > need more work?
> > > > >
> > > > > Follow up!
> > > >
> > > > Ok good as in mm-stable now. Sadly means I don't get to review it but there we
> > > > go.
> > >
> > > Actually this patchset has already been merged upstream:)
>
> Let me try to make things clear.
>
> > Err but this revision was sent _during_ the merge window...?
> >
> > Was sent on 9th Feb on Monday in merge window week 1, with a functional change
> > listed:
> >
> > - Skip batched unmapping for uffd case, reported by Dev. Thanks.
> >
> > And then sent in 2nd batch on 18th Feb (see [0]).
> >
> > So we were ok with 1 week of 'testing' (does anybody actually test -next during
> > the merge window? Was it even sent to -next?) for what appears to be a
> > functional change?
>
> I posted v5 on Dec 26th[0], and it collected quite a few Reviewed-by tags
> and sat in mm-unstable for testing.
>
> Later, Dev reported a uffd-related issue (I hope you recall that
> discussion). I posted a fix[1] for it on Jan 16th, which Andrew accepted.
>
> Since then, the v5 series (plus the fix) continued to be tested in
> mm-unstable. We kept it there mainly because David mentioned he wanted to
> review the series, so we were waiting for his time.
>
> On Feb 9th, after returning from vacation, David reviewed the series
> (thanks, David!). I replied to and addressed all his comments, then posted
> v6 on the same day[2].

OK thanks, I see that now.

I still don't think we should have made any changes _during_ the merge window,
even if they were simple code quality things.

Changing patches then seems just crazy to me, as even code quality stuff can
cause unexpected bugs, and now we're having upstream take it.

Also this speaks to -fix patches just being broken in general.

If you'd just respun with the fix as a v6, then we'd know 'v6 sent on 16th Jan
addressed this' and there'd be no isssue.

Now v5 isn't v5, there's v5 and something-not-v5 and to have a sense of the
testing you have to go read a bunch of email chains.

It also means change logs are now really inaccurate:

Changes from v5:
 - Collect reviewed tags from Ryan, Harry and David. Thanks.
 - Fix some coding style issues (per David).
 - Skip batched unmapping for uffd case, reported by Dev. Thanks.

And that to me means 'v5 didn't have this, v6 does'.

And it's really hard to track timelines for testing.

>
> Additionally, v6 had no functional changes compared to v5 + the fix, and it
> mainly addressed some coding style issues pointed out by David. I also
> discussed this with David off-list, and since there were no functional
> changes, my expectation was that it could still make it into the merge
> window. That is why v6 was merged.

Yeah, we still shouldn't have taken changes to a series DURING the merge window,
it's just crazy.

>
> [0] https://lore.kernel.org/linux-mm/cover.1766631066.git.baolin.wang@linux.alibaba.com/#t
> [1] https://lore.kernel.org/linux-mm/20260116162652.176054-1-baolin.wang@linux.alibaba.com/
> [2] https://lore.kernel.org/all/cover.1770645603.git.baolin.wang@linux.alibaba.com/
>
> > And there was ongoing feedback on this and the v5 series (at [1])?
>
> Regarding the feedback on v5, I believe everything has been addressed.
>
> > This doesn't really feel sane?
> >
> > And now I'm confused as to whether mm-stable patches can collect tags, since
> > presumably this was in mm-stable at the point this respin was done?
> >
> > Maybe I'm missing something here but this doesn't feel like a sane process?
>
> Andrew, David, please correct me if I've missed anything. Also, please let
> me know if there's anything in the process that needs to be improved.
> Thanks.

This isn't on you, it's about the process as a whole. We need clear rules about
when changes will be accepted and when not.

And frankly I think we need to do away with fix patches as a whole based on
this, or at least anything even vaguely non-trivial or that potentially impacts
code.

Thanks, Lorenzo


^ permalink raw reply

* Re: [PATCH v6 14/40] arm_mpam: resctrl: Add boilerplate cpuhp and domain allocation
From: James Morse @ 2026-03-26 12:20 UTC (permalink / raw)
  To: Ben Horgan, Gavin Shan
  Cc: amitsinght, baisheng.gao, baolin.wang, carl, dave.martin, david,
	dfustini, fenghuay, jonathan.cameron, kobak, lcherian,
	linux-arm-kernel, linux-kernel, peternewman, punit.agrawal,
	quic_jiles, reinette.chatre, rohit.mathew, scott, sdonthineni,
	tan.shaopeng, xhao, catalin.marinas, will, corbet, maz, oupton,
	joey.gouly, suzuki.poulose, kvmarm, zengheng4, linux-doc,
	Shaopeng Tan
In-Reply-To: <80915f50-b5c9-4790-81c6-4f08b2af1274@arm.com>

Hi Ben, Gavin,

On 23/03/2026 10:13, Ben Horgan wrote:
> On 3/23/26 06:31, Gavin Shan wrote:
>> On 3/14/26 12:45 AM, Ben Horgan wrote:
>>> From: James Morse <james.morse@arm.com>
>>>
>>> resctrl has its own data structures to describe its resources. We can't use
>>> these directly as we play tricks with the 'MBA' resource, picking the MPAM
>>> controls or monitors that best apply. We may export the same component as
>>> both L3 and MBA.
>>>
>>> Add mpam_resctrl_res[] as the array of class->resctrl mappings we are
>>> exporting, and add the cpuhp hooks that allocated and free the resctrl
>>> domain structures. Only the mpam control feature are considered here and
>>> monitor support will be added later.
>>>
>>> While we're here, plumb in a few other obvious things.
>>>
>>> CONFIG_ARM_CPU_RESCTRL is used to allow this code to be built even though
>>> it can't yet be linked against resctrl.


>> With the following two comments addressed. I don't think none of them are critical
>> given the fact that this series has been respinned to v6 and may be ready for Linux
>> v7.1. If there is still a chance for another respin, they may be worthy to be addressed.
>>
>> Reviewed-by: Gavin Shan <gshan@redhat.com>

I've picked up the change from your second comment, I assume you're happy to keep this
tag. (otherwise shout!)


>>> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
>>> new file mode 100644
>>> index 000000000000..e698b534e3db
>>> --- /dev/null
>>> +++ b/drivers/resctrl/mpam_resctrl.c

>>> +static struct mpam_resctrl_dom *
>>> +mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
>>> +{
>>> +    int err;
>>> +    struct mpam_resctrl_dom *dom;
>>> +    struct rdt_ctrl_domain *ctrl_d;
>>> +    struct mpam_class *class = res->class;
>>> +    struct mpam_component *comp_iter, *ctrl_comp;
>>> +    struct rdt_resource *r = &res->resctrl_res;
>>> +
>>> +    lockdep_assert_held(&domain_list_lock);
>>> +
>>> +    ctrl_comp = NULL;
>>> +    guard(srcu)(&mpam_srcu);
>>> +    list_for_each_entry_srcu(comp_iter, &class->components, class_list,
>>> +                 srcu_read_lock_held(&mpam_srcu)) {
>>> +        if (cpumask_test_cpu(cpu, &comp_iter->affinity)) {
>>> +            ctrl_comp = comp_iter;
>>> +            break;
>>> +        }
>>> +    }
>>> +
>>> +    /* class has no component for this CPU */
>>> +    if (WARN_ON_ONCE(!ctrl_comp))
>>> +        return ERR_PTR(-EINVAL);
>>> +
>>> +    dom = kzalloc_node(sizeof(*dom), GFP_KERNEL, cpu_to_node(cpu));
>>> +    if (!dom)
>>> +        return ERR_PTR(-ENOMEM);
>>> +
>>> +    if (r->alloc_capable) {
>>> +        dom->ctrl_comp = ctrl_comp;
>>> +
>>> +        ctrl_d = &dom->resctrl_ctrl_dom;
>>> +        mpam_resctrl_domain_hdr_init(cpu, ctrl_comp, r->rid, &ctrl_d->hdr);
>>> +        ctrl_d->hdr.type = RESCTRL_CTRL_DOMAIN;
>>> +        err = resctrl_online_ctrl_domain(r, ctrl_d);
>>> +        if (err)
>>> +            goto free_domain;
>>> +
>>> +        mpam_resctrl_domain_insert(&r->ctrl_domains, &ctrl_d->hdr);
>>> +    } else {
>>> +        pr_debug("Skipped control domain online - no controls\n");
>>> +    }
>>> +    return dom;

>> Even though we will never support "r->alloc_capable == false", it's worthy to maintain
>> the consistence in the code level here, meaning @dom needs to be released with a proper
>> error number returned.
>>
>>     if (r->alloc_capable) {
>>         :
>>     } else {
>>         pr_debug("Skipped control domain online - no controls\n");
>>         err = -EINVAL;
>>         goto free_domain;
>>     }
>>
>> Alternatively, the check can be done before locating the component from its calss.
>>
>>     
>>     lockdep_assert_held(&domain_list_lock);
>>
>>     if (!r->alloc_capable) {
>>         pr_debug("Skipped control domain online - no controls\n");
>>         return ERR_PTR(-EINVAL);
>>     }
>>
>>     ctrl_comp = NULL;
> 
> Once monitor support is added later in the series this is no longer an
> error path as monitor only platforms are valid. In order to avoid adding
> a change and then reverting it later in the series I would like to keep
> this as it is.

I've left this as it is - adding the monitoring support builds on top of this.


>>> +int mpam_resctrl_online_cpu(unsigned int cpu)
>>> +{
>>> +    struct mpam_resctrl_res *res;
>>> +    enum resctrl_res_level rid;
>>> +
>>> +    guard(mutex)(&domain_list_lock);
>>> +    for_each_mpam_resctrl_control(res, rid) {
>>> +        struct mpam_resctrl_dom *dom;
>>> +        struct rdt_resource *r = &res->resctrl_res;
>>> +
>>> +        if (!res->class)
>>> +            continue;    // dummy_resource;
>>> +
>>> +        dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
>>> +        if (!dom) {
>>> +            dom = mpam_resctrl_alloc_domain(cpu, res);
>>> +        } else {
>>> +            if (r->alloc_capable) {
>>> +                struct rdt_ctrl_domain *ctrl_d = &dom->resctrl_ctrl_dom;
>>> +
>>> +                mpam_resctrl_online_domain_hdr(cpu, &ctrl_d->hdr);
>>> +            }
>>> +        }
>>> +        if (IS_ERR(dom))
>>> +            return PTR_ERR(dom);
>>> +    }
>>> +
>>
>> I think the "if (IS_ERR(dom))" check can be moved after "dom = mpam_resctrl_alloc_domain(cpu, res)"
>> because it seems the only path where an erroneous domain can be returned.
>>
>>         dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
>>         if (!dom) {
>>             dom = mpam_resctrl_alloc_domain(cpu, res);
>>             if (IS_ERR(dom))
>>                 return PTR_ERR(dom);
>>         } else {
>>             ...
>>         }
> 
> Yes, that would be clearer. I'll make this change if a respin becomes needed.

Applied locally.



Thanks!

James


^ permalink raw reply

* Re: [PATCH 0/4] Add i.MX94 remoteproc support and reset vector handling improvements
From: Peng Fan @ 2026-03-26 12:20 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Mathieu Poirier, Bjorn Andersson, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-remoteproc,
	devicetree, imx, linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <80c7815b-26d9-4876-a44f-3e17b6338dc6@oss.nxp.com>

On Wed, Mar 25, 2026 at 10:41:29AM +0200, Daniel Baluta wrote:
>On 3/23/26 16:32, Mathieu Poirier wrote:
>> On Fri, Mar 20, 2026 at 11:19:06AM +0200, Daniel Baluta wrote:
>>> On 3/12/26 14:36, Peng Fan (OSS) wrote:
>>>> This series adds remoteproc support for the i.MX94 family, including the
>>>> CM70, CM71, and CM33S cores, and introduces a new device‑tree property to
>>>> correctly derive the hardware reset vector for Cortex‑M processors whose
>>>> ELF entry point does not directly correspond to the actual reset address.
>>>>
>>>> Background:
>>>> Cortex‑M processors fetch their initial SP and PC from a fixed reset vector
>>>> table. While ELF images embed the entry point (e_entry), this value is
>>>> not always aligned to the hardware reset address. On platforms such as
>>>> i.MX94 CM33S, masking is required to compute the correct reset vector
>>>> address before programming the SoC reset registers.
>>> What happens if the reset vector is at 0 and the e_entry point is at 0x800...?
>>>
>>> In this case masking will no longer work! Can we implement a generic approach?
>>>
>> I will wait to see an R-B from Daniel before looking at this set.
>>
>> Thanks,
>> Mathieu
>>  
>>
>Hi Mathieu, Peng,
>
>Patchseries mostly looks good to me. The only blocking issue here is how to correctly specify the hardware reset address.
>
>I see two options here:
>
>1) Create a special section in TCM that holds the PC/Stack initial value as concluded here [1]. But this
>
>doesn't work in all the cases 
>
>2) Add a per device data that holds the hardware reset mask that gets applied to entry address read from ELF.
>
>I'm fine going with option 2) and that's because this change is IMX rproc driver specific, it scales well and will be maintained by Peng.

Thanks, I will go with option 2.

Thanks
Peng

>
>thanks,
>
>Daniel.
>
>[1] https://lore.kernel.org/linux-remoteproc/38476dd0-07a6-310f-1fba-2b3021a5b007@kontron.de/
>


^ permalink raw reply

* Re: [PATCH v9 0/5] I2C Mux per channel bus speed
From: Marcus Folkesson @ 2026-03-26 12:17 UTC (permalink / raw)
  To: Wolfram Sang, Peter Rosin, Michael Hennerich, Bartosz Golaszewski,
	Andi Shyti, Andy Shevchenko, Bartosz Golaszewski
  Cc: linux-i2c, linux-kernel, linux-arm-kernel
In-Reply-To: <20260324-i2c-mux-v9-0-5292b0608243@gmail.com>

On Tue, Mar 24, 2026 at 02:54:14PM +0100, Marcus Folkesson wrote:
> This was a RFC on how to implement a feature to have different bus
> speeds on different channels with an I2C multiplexer/switch.
> As no major complaints on the design came up during the review, I
> decided to submit the series without the RFC tag.
> 
> The benefit with this feature is that you may group devices after
> the fastest bus speed they can handle.
> A real-world example is that you could have e.g. a display running @400kHz
> and a smart battery running @100kHz using the same I2C controller.
> 
> There are many corner cases where this may cause a problem for some
> hardware topologies. I've tried to describe those I could think of
> in the documentation, see Patch #5.
> 
> E.g. one risk is that if the mux driver does not disconnect channels
> when Idle, this may cause a higher frequency to "leak" through to
> devices that are supposed to run at lower bus speed.
> This is not only a "problem" for changing bus speed but could also be
> an issue for potential address conflicts.
> 
> This patchset has been used and tested heavily the last months
> on a custom board based on a da850 (DaVinci) platform.
> 
> The implementation is split up into several patches:
> 
> Patch #1 Introduce a callback for the i2c controller to set bus speed
> Patch #2 Introduce functionality to adjust bus speed depending on mux
>          channel.
> Patch #3 Cleanup i2c-davinci driver a bit to prepare it for set_clk_freq
> Parch #4 Implement set_clk_freq for the i2c-davinci driver
> Parch #5 Update documentation with this feature
> 
> Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
> ---

Peter,
Do you have any feedback on this new approach?

Thanks in advance,
Marcus


^ permalink raw reply

* Re: [PATCH v11 03/22] drm: Add new general DRM property "color format"
From: Ville Syrjälä @ 2026-03-26 12:13 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Nicolas Frattaroli, Harry Wentland, Leo Li, Rodrigo Siqueira,
	Alex Deucher, Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan, kernel, amd-gfx, dri-devel,
	linux-kernel, linux-arm-kernel, linux-rockchip, intel-gfx,
	intel-xe, linux-doc, Werner Sembach, Andri Yngvason, Marius Vlad
In-Reply-To: <CAPY8ntCRPgN_ayHMGXFv9OrJrdyakUcUT0rvgY5J=FvdCFb6eA@mail.gmail.com>

On Thu, Mar 26, 2026 at 11:16:12AM +0000, Dave Stevenson wrote:
> On Wed, 25 Mar 2026 at 13:43, Ville Syrjälä
> <ville.syrjala@linux.intel.com> wrote:
> >
> > On Wed, Mar 25, 2026 at 12:49:19PM +0000, Dave Stevenson wrote:
> > > On Tue, 24 Mar 2026 at 16:02, Nicolas Frattaroli
> > > <nicolas.frattaroli@collabora.com> wrote:
> > > >
> > > > Add a new general DRM property named "color format" which can be used by
> > > > userspace to request the display driver to output a particular color
> > > > format.
> > > >
> > > > Possible options are:
> > > >     - auto (setup by default, driver internally picks the color format)
> > > >     - rgb
> > > >     - ycbcr444
> > > >     - ycbcr422
> > > >     - ycbcr420
> > > >
> > > > Drivers should advertise from this list which formats they support.
> > > > Together with this list and EDID data from the sink we should be able
> > > > to relay a list of usable color formats to users to pick from.
> > > >
> > > > Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
> > > > Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> > > > Co-developed-by: Andri Yngvason <andri@yngvason.is>
> > > > Signed-off-by: Andri Yngvason <andri@yngvason.is>
> > > > Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
> > > > Reviewed-by: Maxime Ripard <mripard@kernel.org>
> > > > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> > > > ---
> > > >  drivers/gpu/drm/drm_atomic_helper.c |   5 ++
> > > >  drivers/gpu/drm/drm_atomic_uapi.c   |  11 ++++
> > > >  drivers/gpu/drm/drm_connector.c     | 108 ++++++++++++++++++++++++++++++++++++
> > > >  include/drm/drm_connector.h         | 104 ++++++++++++++++++++++++++++++++++
> > > >  4 files changed, 228 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> > > > index 26953ed6b53e..b7753454b777 100644
> > > > --- a/drivers/gpu/drm/drm_atomic_helper.c
> > > > +++ b/drivers/gpu/drm/drm_atomic_helper.c
> > > > @@ -737,6 +737,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
> > > >                         if (old_connector_state->max_requested_bpc !=
> > > >                             new_connector_state->max_requested_bpc)
> > > >                                 new_crtc_state->connectors_changed = true;
> > > > +
> > > > +                       if (old_connector_state->color_format !=
> > > > +                           new_connector_state->color_format)
> > > > +                               new_crtc_state->connectors_changed = true;
> > > > +
> > > >                 }
> > > >
> > > >                 if (funcs->atomic_check)
> > > > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> > > > index 5bd5bf6661df..dee510c85e59 100644
> > > > --- a/drivers/gpu/drm/drm_atomic_uapi.c
> > > > +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> > > > @@ -935,6 +935,15 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
> > > >                 state->privacy_screen_sw_state = val;
> > > >         } else if (property == connector->broadcast_rgb_property) {
> > > >                 state->hdmi.broadcast_rgb = val;
> > > > +       } else if (property == connector->color_format_property) {
> > > > +               if (val > INT_MAX || !drm_connector_color_format_valid(val)) {
> > > > +                       drm_dbg_atomic(connector->dev,
> > > > +                                      "[CONNECTOR:%d:%s] unknown color format %llu\n",
> > > > +                                      connector->base.id, connector->name, val);
> > > > +                       return -EINVAL;
> > > > +               }
> > > > +
> > > > +               state->color_format = val;
> > > >         } else if (connector->funcs->atomic_set_property) {
> > > >                 return connector->funcs->atomic_set_property(connector,
> > > >                                 state, property, val);
> > > > @@ -1020,6 +1029,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
> > > >                 *val = state->privacy_screen_sw_state;
> > > >         } else if (property == connector->broadcast_rgb_property) {
> > > >                 *val = state->hdmi.broadcast_rgb;
> > > > +       } else if (property == connector->color_format_property) {
> > > > +               *val = state->color_format;
> > > >         } else if (connector->funcs->atomic_get_property) {
> > > >                 return connector->funcs->atomic_get_property(connector,
> > > >                                 state, property, val);
> > > > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> > > > index 47dc53c4a738..e848374dee0b 100644
> > > > --- a/drivers/gpu/drm/drm_connector.c
> > > > +++ b/drivers/gpu/drm/drm_connector.c
> > > > @@ -1388,6 +1388,18 @@ static const u32 hdmi_colorspaces =
> > > >         BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
> > > >         BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER);
> > > >
> > > > +static const u32 hdmi_colorformats =
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
> > > > +
> > > > +static const u32 dp_colorformats =
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
> > > > +
> > > >  /*
> > > >   * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry
> > > >   * Format Table 2-120
> > > > @@ -2940,6 +2952,102 @@ int drm_connector_attach_colorspace_property(struct drm_connector *connector)
> > > >  }
> > > >  EXPORT_SYMBOL(drm_connector_attach_colorspace_property);
> > > >
> > > > +/**
> > > > + * drm_connector_attach_color_format_property - create and attach color format property
> > > > + * @connector: connector to create the color format property on
> > > > + * @supported_color_formats: bitmask of bit-shifted &enum drm_output_color_format
> > > > + *                           values the connector supports
> > > > + *
> > > > + * Called by a driver to create a color format property. The property is
> > > > + * attached to the connector automatically on success.
> > > > + *
> > > > + * @supported_color_formats should only include color formats the connector
> > > > + * type can actually support.
> > > > + *
> > > > + * Returns:
> > > > + * 0 on success, negative errno on error
> > > > + */
> > > > +int drm_connector_attach_color_format_property(struct drm_connector *connector,
> > > > +                                              unsigned long supported_color_formats)
> > > > +{
> > > > +       struct drm_device *dev = connector->dev;
> > > > +       struct drm_prop_enum_list enum_list[DRM_CONNECTOR_COLOR_FORMAT_COUNT];
> > > > +       unsigned int i = 0;
> > > > +       unsigned long fmt;
> > > > +
> > > > +       if (connector->color_format_property)
> > > > +               return 0;
> > > > +
> > > > +       if (!supported_color_formats) {
> > > > +               drm_err(dev, "No supported color formats provided on [CONNECTOR:%d:%s]\n",
> > > > +                       connector->base.id, connector->name);
> > > > +               return -EINVAL;
> > > > +       }
> > > > +
> > > > +       if (supported_color_formats & ~GENMASK(DRM_OUTPUT_COLOR_FORMAT_COUNT - 1, 0)) {
> > > > +               drm_err(dev, "Unknown color formats provided on [CONNECTOR:%d:%s]\n",
> > > > +                       connector->base.id, connector->name);
> > > > +               return -EINVAL;
> > > > +       }
> > > > +
> > > > +       switch (connector->connector_type) {
> > > > +       case DRM_MODE_CONNECTOR_HDMIA:
> > > > +       case DRM_MODE_CONNECTOR_HDMIB:
> > > > +               if (supported_color_formats & ~hdmi_colorformats) {
> > > > +                       drm_err(dev, "Color formats not allowed for HDMI on [CONNECTOR:%d:%s]\n",
> > > > +                               connector->base.id, connector->name);
> > > > +                       return -EINVAL;
> > > > +               }
> > > > +               break;
> > > > +       case DRM_MODE_CONNECTOR_DisplayPort:
> > > > +       case DRM_MODE_CONNECTOR_eDP:
> > > > +               if (supported_color_formats & ~dp_colorformats) {
> > > > +                       drm_err(dev, "Color formats not allowed for DP on [CONNECTOR:%d:%s]\n",
> > > > +                               connector->base.id, connector->name);
> > > > +                       return -EINVAL;
> > > > +               }
> > > > +               break;
> > > > +       }
> > > > +
> > > > +       enum_list[0].name = "AUTO";
> > > > +       enum_list[0].type = DRM_CONNECTOR_COLOR_FORMAT_AUTO;
> > > > +
> > > > +       for_each_set_bit(fmt, &supported_color_formats, DRM_OUTPUT_COLOR_FORMAT_COUNT) {
> > > > +               switch (fmt) {
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_RGB444:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
> > > > +                       break;
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
> > > > +                       break;
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR422;
> > > > +                       break;
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
> > > > +                       break;
> > > > +               default:
> > > > +                       drm_warn(dev, "Unknown supported format %ld on [CONNECTOR:%d:%s]\n",
> > > > +                                fmt, connector->base.id, connector->name);
> > > > +                       continue;
> > > > +               }
> > > > +               enum_list[i].name = drm_hdmi_connector_get_output_format_name(fmt);
> > > > +       }
> > > > +
> > > > +       connector->color_format_property =
> > > > +               drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "color format",
> > > > +                                        enum_list, i + 1);
> > > > +
> > > > +       if (!connector->color_format_property)
> > > > +               return -ENOMEM;
> > > > +
> > > > +       drm_object_attach_property(&connector->base, connector->color_format_property,
> > > > +                                  DRM_CONNECTOR_COLOR_FORMAT_AUTO);
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +EXPORT_SYMBOL(drm_connector_attach_color_format_property);
> > > > +
> > > >  /**
> > > >   * drm_connector_atomic_hdr_metadata_equal - checks if the hdr metadata changed
> > > >   * @old_state: old connector state to compare
> > > > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > > > index af8b92d2d5b7..bd549f912b76 100644
> > > > --- a/include/drm/drm_connector.h
> > > > +++ b/include/drm/drm_connector.h
> > > > @@ -571,14 +571,102 @@ enum drm_colorspace {
> > > >   *   YCbCr 4:2:2 output format (ie. with horizontal subsampling)
> > > >   * @DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
> > > >   *   YCbCr 4:2:0 output format (ie. with horizontal and vertical subsampling)
> > > > + * @DRM_OUTPUT_COLOR_FORMAT_COUNT:
> > > > + *   Number of valid output color format values in this enum
> > > >   */
> > > >  enum drm_output_color_format {
> > > >         DRM_OUTPUT_COLOR_FORMAT_RGB444 = 0,
> > > >         DRM_OUTPUT_COLOR_FORMAT_YCBCR444,
> > > >         DRM_OUTPUT_COLOR_FORMAT_YCBCR422,
> > > >         DRM_OUTPUT_COLOR_FORMAT_YCBCR420,
> > > > +       DRM_OUTPUT_COLOR_FORMAT_COUNT,
> > > >  };
> > > >
> > > > +/**
> > > > + * enum drm_connector_color_format - Connector Color Format Request
> > > > + *
> > > > + * This enum, unlike &enum drm_output_color_format, is used to specify requests
> > > > + * for a specific color format on a connector through the DRM "color format"
> > > > + * property. The difference is that it has an "AUTO" value to specify that
> > > > + * no specific choice has been made.
> > > > + */
> > > > +enum drm_connector_color_format {
> > > > +       /**
> > > > +        * @DRM_CONNECTOR_COLOR_FORMAT_AUTO: The driver or display protocol
> > > > +        * helpers should pick a suitable color format. All implementations of a
> > > > +        * specific display protocol must behave the same way with "AUTO", but
> > > > +        * different display protocols do not necessarily have the same "AUTO"
> > > > +        * semantics.
> > > > +        *
> > > > +        * For HDMI, "AUTO" picks RGB, but falls back to YCbCr 4:2:0 if the
> > > > +        * bandwidth required for full-scale RGB is not available, or the mode
> > > > +        * is YCbCr 4:2:0-only, as long as the mode and output both support
> > > > +        * YCbCr 4:2:0.
> > >
> > > Is there a reason you propose dropping back to YCbCr 4:2:0 without
> > > trying YCbCr 4:2:2 first? Minimising the subsampling is surely
> > > beneficial, and vc4 for one can do 4:2:2 but not 4:2:0.
> >
> > On HDMI 4:2:2 is always 12bpc, so it doesn't save any bandwidth
> > compared to 8bpc 4:4:4.
> 
> It does save bandwidth against 10 or 12bpc RGB 4:4:4.
> 
> Or is the implication that max_bpc = 12 and
> DRM_CONNECTOR_COLOR_FORMAT_AUTO should drop bpc down to 8 and select
> RGB in preference to selecting 4:2:2?

Yeah, YCbCr has all kinds of extra complications compared to RGB, so
the policy is to use RGB if possible, and only fall back to YCbCr as a
last resort. And in that case 4:2:0 is the only thing that can help.

-- 
Ville Syrjälä
Intel


^ permalink raw reply

* Re: [PATCH v3 5/9] mfd: mt6397: Add support for MT6392 pmic
From: Lee Jones @ 2026-03-26 12:10 UTC (permalink / raw)
  To: Luca Leonardo Scorcia
  Cc: linux-mediatek, Fabien Parent, Val Packett, Dmitry Torokhov,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sen Chu,
	Sean Wang, Macpaul Lin, Matthias Brugger,
	AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
	Mark Brown, Julien Massot, Gary Bisson, Louis-Alexis Eyraud,
	Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
	linux-arm-kernel, linux-gpio
In-Reply-To: <20260317184507.523060-6-l.scorcia@gmail.com>

On Tue, 17 Mar 2026, Luca Leonardo Scorcia wrote:

> From: Fabien Parent <parent.f@gmail.com>
> 
> Update the MT6397 MFD driver to support 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>
> ---
>  drivers/mfd/mt6397-core.c            |  46 +++
>  drivers/mfd/mt6397-irq.c             |   8 +
>  include/linux/mfd/mt6392/core.h      |  42 +++
>  include/linux/mfd/mt6392/registers.h | 487 +++++++++++++++++++++++++++
>  include/linux/mfd/mt6397/core.h      |   1 +
>  5 files changed, 584 insertions(+)
>  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 3e58d0764c7e..c4b86a44c68b 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"),
> @@ -253,6 +268,26 @@ static const struct mfd_cell mt6359_devs[] = {
>  	},
>  };
>  
> +static const struct mfd_cell mt6392_devs[] = {
> +	{
> +		.name = "mt6392-rtc",
> +		.num_resources = ARRAY_SIZE(mt6392_rtc_resources),
> +		.resources = mt6392_rtc_resources,
> +		.of_compatible = "mediatek,mt6392-rtc",
> +	}, {
> +		.name = "mt6392-regulator",
> +		.of_compatible = "mediatek,mt6392-regulator",
> +	}, {
> +		.name = "mt6392-pinctrl",
> +		.of_compatible = "mediatek,mt6392-pinctrl",
> +	}, {
> +		.name = "mt6392-keys",
> +		.num_resources = ARRAY_SIZE(mt6392_keys_resources),
> +		.resources = mt6392_keys_resources,
> +		.of_compatible = "mediatek,mt6392-keys"
> +	},
> +};
> +
>  static const struct mfd_cell mt6397_devs[] = {
>  	{
>  		.name = "mt6397-rtc",
> @@ -335,6 +370,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,

I'm not really sure what came over me when I accepted this 6 years ago,
but I have a _strong_ aversion to MFD data being passed through the OF APIs.

Before this patch lands, please could you refactor this driver to only
pass through an identifier through mt6397_of_match[*].data.  Then, you
can match on that via a switch statement where you can allocate each
device's data structures.

This is how the vast majority of MFD drivers work so there should be
lots of examples to work through to make this trivial.

> +	.cell_size = ARRAY_SIZE(mt6392_devs),
> +	.irq_init = mt6397_irq_init,
> +};

-- 
Lee Jones [李琼斯]


^ permalink raw reply

* [PATCH net-next v2 4/4] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver
From: Louis-Alexis Eyraud @ 2026-03-26 12:04 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Andrew Lunn, Heiner Kallweit,
	Russell King
  Cc: kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	Louis-Alexis Eyraud
In-Reply-To: <20260326-add-airoha-an8801-support-v2-0-1a42d6b6050f@collabora.com>

From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>

Introduce a driver for the Airoha AN8801R Series Gigabit Ethernet
PHY; this currently supports setting up PHY LEDs, 10/100M, 1000M
speeds, and Wake on LAN and PHY interrupts.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 drivers/net/phy/Kconfig      |    6 +
 drivers/net/phy/Makefile     |    1 +
 drivers/net/phy/air_an8801.c | 1115 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1122 insertions(+)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index b6b1cde7e51fa1e470bfe210c8764a193449acb5..4dd77ba487763eaf16c2b390feb237e667f76746 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -90,6 +90,12 @@ config AS21XXX_PHY
 	  AS21210PB1 that all register with the PHY ID 0x7500 0x7500
 	  before the firmware is loaded.
 
+config AIR_AN8801_PHY
+	tristate "Airoha AN8801 Gigabit PHY"
+	select AIR_NET_PHYLIB
+	help
+	  Currently supports the Airoha AN8801R PHY.
+
 config AIR_EN8811H_PHY
 	tristate "Airoha EN8811H 2.5 Gigabit PHY"
 	select AIR_NET_PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 7cf1fa9e12cb6073a9e68c0ffa6284b361b80487..de660ae949453d99f8a383ca0c0e3cf3f1a14922 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -29,6 +29,7 @@ obj-y				+= $(sfp-obj-y) $(sfp-obj-m)
 
 obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
+obj-$(CONFIG_AIR_AN8801_PHY)	+= air_an8801.o
 obj-$(CONFIG_AIR_EN8811H_PHY)   += air_en8811h.o
 obj-$(CONFIG_AIR_NET_PHYLIB)	+= air_phy_lib.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
diff --git a/drivers/net/phy/air_an8801.c b/drivers/net/phy/air_an8801.c
new file mode 100644
index 0000000000000000000000000000000000000000..53ade9665fe9e08010fe208f760051f1b621a128
--- /dev/null
+++ b/drivers/net/phy/air_an8801.c
@@ -0,0 +1,1115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for the Airoha AN8801 Gigabit PHY.
+ *
+ * Copyright (C) 2025 Airoha Technology Corp.
+ * Copyright (C) 2025 Collabora Ltd.
+ *                    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+#include <linux/pm_wakeirq.h>
+
+#include "air_phy_lib.h"
+
+#define AN8801R_PHY_ID			0xc0ff0421
+
+/* MII Registers */
+
+/* MII Registers - Airoha Page 1 */
+#define AN8801_EXT_REG_PHY		0x14
+#define   AN8801_EXT_PHY_STATUS0	GENMASK(1, 0)
+#define   AN8801_EXT_PHY_DOWNSHIFT_CTL	GENMASK(3, 2) /* 2 to 5 1G auto-neg attempts (0..3) */
+#define   AN8801_EXT_PHY_DOWNSHIFT_EN	BIT(4)
+#define   AN8801_EXT_PHY_CTRL0		BIT(5)
+#define   AN8801_EXT_PHY_STATUS1	GENMASK(8, 6)
+#define   AN8801_EXT_PHY_CTRL1		GENMASK(14, 9)
+
+/* MII Registers - Airoha Page 4 */
+#define AN8801_PBUS_ACCESS		BIT(28)
+#define AN8801_PBUS_EPHY_ACCESS		BIT(24)
+#define AN8801_PBUS_CL22_ACCESS		BIT(23)
+
+/* BPBUS Registers */
+#define AN8801_BPBUS_REG_LED_GPIO	0x54
+#define AN8801_BPBUS_REG_LED_ID_SEL	0x58
+#define   LED_ID_GPIO_SEL(led, gpio)	((led) << ((gpio) * 3))
+#define AN8801_BPBUS_REG_GPIO_MODE	0x70
+#define AN8801_BPBUS_REG_PHY_IRQ_GPIO	0x7c
+#define   AN8801_PHY_IRQ_GPIO_NUM_MASK	GENMASK(19, 16)
+#define   AN8801_PHY_IRQ_GPIO_NUM	1
+
+#define AN8801_BPBUS_REG_CKO		0x1a4
+#define AN8801_CKO_OUTPUT_MODE_AUTO	3
+
+#define AN8801_BPBUS_REG_LINK_MODE	0x5054
+#define  AN8801_BPBUS_LINK_MODE_1000	BIT(0)
+
+#define AN8801_BPBUS_REG_BYPASS_PTP	0x21c004
+#define   AN8801_BYP_PTP_SGMII_TO_GPHY	BIT(8)
+#define   AN8801_BYP_PTP_RGMII_TO_GPHY	BIT(0)
+
+#define AN8801_BPBUS_REG_TXDLY_STEP	0x21c024
+#define   RGMII_DELAY_STEP_MASK		GENMASK(2, 0)
+#define   RGMII_DELAY_NO_STEP		0
+#define   RGMII_DELAY_STEP_1		1
+#define   RGMII_DELAY_STEP_2		2
+#define   RGMII_DELAY_STEP_3		3
+#define   RGMII_DELAY_STEP_4		4
+#define   RGMII_DELAY_STEP_5		5
+#define   RGMII_DELAY_STEP_6		6
+#define   RGMII_DELAY_STEP_7		7
+#define   RGMII_TXDELAY_FORCE_MODE	BIT(24)
+
+#define AN8801_RGMII_TXDELAY_DEFAULT	RGMII_DELAY_STEP_4 /* 1.883ns delay */
+
+#define AN8801_BPBUS_REG_RXDLY_STEP	0x21c02c
+#define   RGMII_RXDELAY_ALIGN		BIT(4)
+#define   RGMII_RXDELAY_FORCE_MODE	BIT(24)
+
+#define AN8801_RGMII_RXDELAY_DEFAULT	RGMII_DELAY_NO_STEP /* 1.992ns delay */
+
+#define AN8801_BPBUS_REG_EFIFO_CTL(x)	(0x270004 + (0x100 * (x))) /* 0..2 */
+#define   AN8801_EFIFO_ALL_EN		GENMASK(7, 0)
+#define   AN8801_EFIFO_RX_EN		BIT(0)
+#define   AN8801_EFIFO_TX_EN		BIT(1)
+#define   AN8801_EFIFO_RX_CLK_EN	BIT(2)
+#define   AN8801_EFIFO_TX_CLK_EN	BIT(3)
+#define   AN8801_EFIFO_RX_EEE_EN	BIT(4)
+#define   AN8801_EFIFO_TX_EEE_EN	BIT(5)
+#define   AN8801_EFIFO_RX_ODD_NIBBLE_EN	BIT(6)
+#define   AN8801_EFIFO_TX_ODD_NIBBLE_EN	BIT(7)
+
+#define AN8801_BPBUS_REG_WOL_MAC_16_47	0x285114
+#define AN8801_BPBUS_REG_WOL_MAC_0_15	0x285118
+
+#define AN8801_BPBUS_REG_WAKEUP_CTL1	0x285400
+#define   AN8801_WOL_WAKE_MAGIC_EN	GENMASK(3, 1)
+#define   AN8801_WOL_WAKE_LNKCHG_EN	BIT(4)
+
+#define AN8801_BPBUS_REG_WAKEUP_CTL2	0x285404
+#define   AN8801_WAKE_OUT_TYPE_PULSE	BIT(0) /* Set/Unset: Pulse/Static */
+#define   AN8801_WAKE_OUT_POLARITY_NEG	BIT(1) /* Set/Unset: Negative/Positive */
+#define   AN8801_WAKE_OUT_WIDTH		GENMASK(2, 3)
+#define    AN8801_WAKE_OUT_84MS		0
+#define    AN8801_WAKE_OUT_168MS	1
+#define    AN8801_WAKE_OUT_336MS	2
+#define    AN8801_WAKE_OUT_672MS	3
+#define   AN8801_WAKE_OUT_EN		BIT(4)
+#define   AN8801_PME_WAKEUP_CLR		BIT(8)
+
+#define AN8801_BPBUS_REG_WAKE_IRQ_EN	0x285700
+#define AN8801_BPBUS_REG_WAKE_IRQ_STS	0x285704
+#define   AN8801_IRQ_WAKE_LNKCHG	BIT(0) /* Wake on link change */
+#define   AN8801_IRQ_WAKE_UNIPKT	BIT(1) /* Wake on unicast packet */
+#define   AN8801_IRQ_WAKE_MULPKT	BIT(2) /* Wake on multicast packet */
+#define   AN8801_IRQ_WAKE_BCPKT		BIT(3) /* Wake on broadcast packet */
+#define   AN8801_IRQ_WAKE_MAGICPKT	BIT(4) /* Wake on magic packet */
+#define   AN8801_IRQ_WAKE_ALL		GENMASK(4, 0)
+
+/* MDIO_MMD_VEND1 Registers */
+#define AN8801_PHY_TX_PAIR_DLY_SEL_GBE	0x13
+#define   AN8801_PHY_PAIR_DLY_SEL_A_GBE	GENMASK(14, 12)
+#define   AN8801_PHY_PAIR_DLY_SEL_B_GBE	GENMASK(10, 8)
+#define   AN8801_PHY_PAIR_DLY_SEL_C_GBE	GENMASK(6, 4)
+#define   AN8801_PHY_PAIR_DLY_SEL_D_GBE	GENMASK(2, 0)
+#define AN8801_PHY_RXADC_CTRL		0xd8
+#define   AN8801_PHY_RXADC_SAMP_PHSEL_A	BIT(12)
+#define   AN8801_PHY_RXADC_SAMP_PHSEL_B	BIT(8)
+#define   AN8801_PHY_RXADC_SAMP_PHSEL_C	BIT(4)
+#define   AN8801_PHY_RXADC_SAMP_PHSEL_D	BIT(0)
+#define AN8801_PHY_RXADC_REV_0		0xd9
+#define   AN8801_PHY_RXADC_REV_MASK_A	GENMASK(15, 8)
+#define   AN8801_PHY_RXADC_REV_MASK_B	GENMASK(7, 0)
+#define AN8801_PHY_RXADC_REV_1		0xda
+#define   AN8801_PHY_RXADC_REV_MASK_C	GENMASK(15, 8)
+#define   AN8801_PHY_RXADC_REV_MASK_D	GENMASK(7, 0)
+
+/* MDIO_MMD_VEND2 Registers */
+#define LED_BCR				0x21
+#define   LED_BCR_MODE_MASK		GENMASK(1, 0)
+#define   LED_BCR_TIME_TEST		BIT(2)
+#define   LED_BCR_CLK_EN		BIT(3)
+#define   LED_BCR_EVT_ALL		BIT(4)
+#define   LED_BCR_EXT_CTRL		BIT(15)
+#define   LED_BCR_MODE_DISABLE		0
+#define   LED_BCR_MODE_2LED		1
+#define   LED_BCR_MODE_3LED_1		2
+#define   LED_BCR_MODE_3LED_2		3
+
+#define LED_ON_DUR			0x22
+#define   LED_ON_DUR_MASK		GENMASK(15, 0)
+
+#define LED_BLINK_DUR			0x23
+#define   LED_BLINK_DUR_MASK		GENMASK(15, 0)
+
+#define LED_ON_CTRL(i)			(0x24 + ((i) * 2))
+#define   LED_ON_EVT_MASK		GENMASK(6, 0)
+#define   LED_ON_EVT_LINK_1000M		BIT(0)
+#define   LED_ON_EVT_LINK_100M		BIT(1)
+#define   LED_ON_EVT_LINK_10M		BIT(2)
+#define   LED_ON_EVT_LINK_DN		BIT(3)
+#define   LED_ON_EVT_FDX		BIT(4)
+#define   LED_ON_EVT_HDX		BIT(5)
+#define   LED_ON_EVT_FORCE		BIT(6)
+#define   LED_ON_POL			BIT(14)
+#define   LED_ON_EN			BIT(15)
+
+#define LED_BLINK_CTRL(i)		(0x25 + ((i) * 2))
+#define LED_BLINK_EVT_MASK		GENMASK(9, 0)
+#define LED_BLINK_EVT_1000M_TX		BIT(0)
+#define LED_BLINK_EVT_1000M_RX		BIT(1)
+#define LED_BLINK_EVT_100M_TX		BIT(2)
+#define LED_BLINK_EVT_100M_RX		BIT(3)
+#define LED_BLINK_EVT_10M_TX		BIT(4)
+#define LED_BLINK_EVT_10M_RX		BIT(5)
+#define LED_BLINK_EVT_COLLISION		BIT(6)
+#define LED_BLINK_EVT_RX_CRC_ERR	BIT(7)
+#define LED_BLINK_EVT_RX_IDLE_ERR	BIT(8)
+#define LED_BLINK_EVT_FORCE		BIT(9)
+
+#define AN8801R_NUM_LEDS		3
+#define AN8801_PERIOD_SHIFT		15
+#define AN8801_PERIOD_UNIT		32768 /* (1 << AN8801_PERIOD_SHIFT) */
+#define AN8801_MAX_PERIOD_MS		2147
+
+#define LED_BLINK_DURATION_UNIT		780
+#define LED_BLINK_DURATION(f)		(LED_BLINK_DURATION_UNIT << (f))
+
+#define AN8801_LED_DURATION_UNIT_US	32768
+
+#define AN8801_REG_PHY_INTERNAL0	0x600
+#define AN8801_REG_PHY_INTERNAL1	0x601
+#define   AN8801_PHY_INTFUNC_MASK	GENMASK(15, 0) /* PHY internal functions */
+
+enum an8801r_led_fn {
+	AN8801R_LED_FN_NONE,
+	AN8801R_LED_FN_LINK,
+	AN8801R_LED_FN_ACTIVITY,
+	AN8801R_LED_FN_MAX,
+};
+
+struct an8801r_priv {
+	bool wake_magic_enabled;
+	bool wake_lnkchg_enabled;
+};
+
+static int an8801_buckpbus_reg_rmw(struct phy_device *phydev,
+				   u32 addr, u32 mask, u32 set)
+{
+	return air_phy_buckpbus_reg_modify(phydev,
+					   addr | AN8801_PBUS_ACCESS,
+					   mask, set);
+}
+
+static int an8801_buckpbus_reg_set_bits(struct phy_device *phydev,
+					u32 addr, u32 mask)
+{
+	return air_phy_buckpbus_reg_modify(phydev,
+					   addr | AN8801_PBUS_ACCESS,
+					   mask, mask);
+}
+
+static int an8801_buckpbus_reg_clear_bits(struct phy_device *phydev,
+					  u32 addr, u32 mask)
+{
+	return air_phy_buckpbus_reg_modify(phydev,
+					   addr | AN8801_PBUS_ACCESS,
+					   mask, 0);
+}
+
+static int an8801_buckpbus_reg_write(struct phy_device *phydev, u32 addr,
+				     u32 data)
+{
+	return air_phy_buckpbus_reg_write(phydev,
+					  addr | AN8801_PBUS_ACCESS,
+					  data);
+}
+
+static int an8801_buckpbus_reg_read(struct phy_device *phydev, u32 addr,
+				    u32 *data)
+{
+	return air_phy_buckpbus_reg_read(phydev,
+					 addr | AN8801_PBUS_ACCESS,
+					 data);
+}
+
+static u32 an8801r_led_blink_ms_to_hw(unsigned long req_ms)
+{
+	u32 req_ns, regval;
+
+	if (req_ms > AN8801_MAX_PERIOD_MS)
+		req_ms = AN8801_MAX_PERIOD_MS;
+
+	req_ns = req_ms * 1000000;
+
+	/* Round to the nearest period unit... */
+	regval = req_ns + (AN8801_PERIOD_UNIT / 2);
+
+	/* ...and now divide by the full period */
+	regval >>= AN8801_PERIOD_SHIFT;
+
+	return regval;
+}
+
+static int an8801r_led_blink_set(struct phy_device *phydev, u8 index,
+				 unsigned long *delay_on,
+				 unsigned long *delay_off)
+{
+	u32 hw_delay_on, hw_delay_off;
+	bool blink;
+	int ret;
+
+	if (index >= AN8801R_NUM_LEDS)
+		return -EINVAL;
+
+	if (delay_on && delay_off) {
+		blink = true;
+
+		if (*delay_on == 0 || *delay_off == 0) {
+			*delay_on = 64;
+			*delay_off = 64;
+		}
+
+		hw_delay_on = an8801r_led_blink_ms_to_hw(*delay_on);
+		hw_delay_off = an8801r_led_blink_ms_to_hw(*delay_off);
+	} else {
+		blink = false;
+	}
+
+	if (blink) {
+		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_DUR,
+				    LED_BLINK_DURATION(hw_delay_on));
+		if (ret)
+			goto error;
+
+		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_DUR,
+				    LED_BLINK_DURATION(hw_delay_off) >> 1);
+		if (ret)
+			goto error;
+	}
+
+	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+			     LED_ON_EN, blink ? LED_ON_EN : 0);
+	if (ret)
+		return ret;
+
+	return 0;
+error:
+	phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+		       LED_ON_EN, 0);
+	return ret;
+}
+
+static int an8801r_led_brightness_set(struct phy_device *phydev, u8 index,
+				      enum led_brightness value)
+{
+	int ret;
+
+	if (index >= AN8801R_NUM_LEDS)
+		return -EINVAL;
+
+	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+			     LED_ON_EVT_MASK,
+			     (value == LED_OFF) ? 0 : LED_ON_EVT_FORCE);
+	if (ret)
+		return ret;
+
+	return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+			      LED_ON_EN, (value == LED_OFF) ? 0 : LED_ON_EN);
+}
+
+static int an8801r_led_hw_control_get(struct phy_device *phydev, u8 index,
+				      unsigned long *rules)
+{
+	int on, blink;
+
+	on = phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index));
+	if (on < 0)
+		return on;
+
+	blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(index));
+	if (blink < 0)
+		return blink;
+
+	if (FIELD_GET(LED_ON_EVT_LINK_10M, on))
+		__set_bit(TRIGGER_NETDEV_LINK_10, rules);
+
+	if (FIELD_GET(LED_ON_EVT_LINK_100M, on))
+		__set_bit(TRIGGER_NETDEV_LINK_100, rules);
+
+	if (FIELD_GET(LED_ON_EVT_LINK_1000M, on))
+		__set_bit(TRIGGER_NETDEV_LINK_1000, rules);
+
+	if (FIELD_GET(LED_ON_EVT_LINK_10M, on) &&
+	    FIELD_GET(LED_ON_EVT_LINK_100M, on) &&
+	    FIELD_GET(LED_ON_EVT_LINK_1000M, on))
+		__set_bit(TRIGGER_NETDEV_LINK, rules);
+
+	if (FIELD_GET(LED_BLINK_EVT_10M_RX, blink) ||
+	    FIELD_GET(LED_BLINK_EVT_100M_RX, blink) ||
+	    FIELD_GET(LED_BLINK_EVT_1000M_RX, blink))
+		__set_bit(TRIGGER_NETDEV_RX, rules);
+
+	if (FIELD_GET(LED_BLINK_EVT_10M_TX, blink) ||
+	    FIELD_GET(LED_BLINK_EVT_100M_TX, blink) ||
+	    FIELD_GET(LED_BLINK_EVT_1000M_TX, blink))
+		__set_bit(TRIGGER_NETDEV_TX, rules);
+
+	if (FIELD_GET(LED_BLINK_EVT_RX_CRC_ERR, blink))
+		__set_bit(TRIGGER_NETDEV_RX_ERR, rules);
+
+	return 0;
+}
+
+static int an8801r_led_trig_to_hw(unsigned long rules, u16 *on, u16 *blink)
+{
+	if (test_bit(TRIGGER_NETDEV_LINK_10, &rules))
+		*on |= LED_ON_EVT_LINK_10M;
+
+	if (test_bit(TRIGGER_NETDEV_LINK_100, &rules))
+		*on |= LED_ON_EVT_LINK_100M;
+
+	if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules))
+		*on |= LED_ON_EVT_LINK_1000M;
+
+	if (test_bit(TRIGGER_NETDEV_LINK, &rules)) {
+		*on |= LED_ON_EVT_LINK_10M;
+		*on |= LED_ON_EVT_LINK_100M;
+		*on |= LED_ON_EVT_LINK_1000M;
+	}
+
+	if (test_bit(TRIGGER_NETDEV_RX, &rules)) {
+		*blink |= LED_BLINK_EVT_10M_RX;
+		*blink |= LED_BLINK_EVT_100M_RX;
+		*blink |= LED_BLINK_EVT_1000M_RX;
+	}
+
+	if (test_bit(TRIGGER_NETDEV_TX, &rules)) {
+		*blink |= LED_BLINK_EVT_10M_TX;
+		*blink |= LED_BLINK_EVT_100M_TX;
+		*blink |= LED_BLINK_EVT_1000M_TX;
+	}
+
+	if (test_bit(TRIGGER_NETDEV_RX_ERR, &rules))
+		*blink |= LED_BLINK_EVT_RX_CRC_ERR;
+
+	if (rules && !*on && !*blink)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static int an8801r_led_hw_is_supported(struct phy_device *phydev, u8 index,
+				       unsigned long rules)
+{
+	u16 on = 0, blink = 0;
+
+	if (index >= AN8801R_NUM_LEDS)
+		return -EINVAL;
+
+	return an8801r_led_trig_to_hw(rules, &on, &blink);
+}
+
+static int an8801r_led_hw_control_set(struct phy_device *phydev, u8 index,
+				      unsigned long rules)
+{
+	u16 on = 0, blink = 0;
+	int ret;
+
+	if (index >= AN8801R_NUM_LEDS)
+		return -EINVAL;
+
+	ret = an8801r_led_trig_to_hw(rules, &on, &blink);
+	if (ret)
+		return ret;
+
+	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+			     LED_ON_EVT_MASK, on);
+	if (ret)
+		return ret;
+
+	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(index),
+			     LED_BLINK_EVT_MASK, blink);
+
+	if (ret)
+		return ret;
+
+	return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+			      LED_ON_EN, on | blink ? LED_ON_EN : 0);
+}
+
+static int an8801r_led_polarity_set(struct phy_device *phydev, int index,
+				    unsigned long modes)
+{
+	unsigned long mode;
+	bool active_high;
+
+	if (index >= AN8801R_NUM_LEDS)
+		return -EINVAL;
+
+	for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
+		switch (mode) {
+		case PHY_LED_ACTIVE_HIGH:
+			active_high = true;
+			break;
+		case PHY_LED_ACTIVE_LOW:
+			active_high = false;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
+			      LED_ON_POL, active_high ? LED_ON_POL : 0);
+}
+
+static int an8801r_led_init(struct phy_device *phydev, u8 *led_cfg)
+{
+	int led_id, ret;
+
+	/* Set LED BCR Enable */
+	ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, LED_BCR,
+			       LED_BCR_EXT_CTRL | LED_BCR_CLK_EN);
+	if (ret)
+		return ret;
+
+	for (led_id = 0; led_id < AN8801R_NUM_LEDS; led_id++) {
+		unsigned long led_trigger = 0;
+		u32 led_gpio = led_id + 1;
+
+		switch (led_cfg[led_id]) {
+		case AN8801R_LED_FN_LINK:
+			led_trigger = BIT(TRIGGER_NETDEV_LINK);
+			break;
+		case AN8801R_LED_FN_ACTIVITY:
+			led_trigger = BIT(TRIGGER_NETDEV_RX) |
+				    BIT(TRIGGER_NETDEV_TX);
+			break;
+		default:
+			led_trigger = 0;
+			break;
+		}
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_LED_GPIO,
+						   BIT(led_gpio));
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_LED_ID_SEL,
+						   LED_ID_GPIO_SEL(led_id,
+								   led_gpio));
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_clear_bits(phydev,
+						     AN8801_BPBUS_REG_GPIO_MODE,
+						     BIT(led_gpio));
+		if (ret)
+			return ret;
+
+		if (!led_trigger)
+			continue;
+
+		ret = an8801r_led_hw_control_set(phydev, led_id, led_trigger);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int an8801r_reset_wake(struct phy_device *phydev)
+{
+	struct an8801r_priv *priv = phydev->priv;
+	u32 reg_val = 0;
+	int ret;
+
+	/* Enable wakeup clear and disable wake up output */
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL2,
+					AN8801_PME_WAKEUP_CLR |
+					AN8801_WAKE_OUT_POLARITY_NEG);
+	if (ret)
+		return ret;
+
+	/* Clear WAKEUP_CTL1 register before enabling the wakeup events
+	 * again
+	 */
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL1,
+					0);
+	if (ret)
+		return ret;
+
+	if (priv->wake_magic_enabled)
+		reg_val |= AN8801_WOL_WAKE_MAGIC_EN;
+
+	if (priv->wake_lnkchg_enabled)
+		reg_val |= AN8801_WOL_WAKE_LNKCHG_EN;
+
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL1,
+					reg_val);
+	if (ret)
+		return ret;
+
+	/* Disable wake up clear and re-enable wake up output */
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL2,
+					AN8801_WAKE_OUT_POLARITY_NEG |
+					AN8801_WAKE_OUT_EN);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int an8801r_ack_interrupt(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Reset wake status */
+	ret = an8801r_reset_wake(phydev);
+	if (ret)
+		return ret;
+
+	/* Clear the interrupts by writing the reg */
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKE_IRQ_STS,
+					AN8801_IRQ_WAKE_ALL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int an8801r_config_intr(struct phy_device *phydev)
+{
+	int ret;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+		u32 val = FIELD_PREP(AN8801_PHY_IRQ_GPIO_NUM_MASK,
+				     AN8801_PHY_IRQ_GPIO_NUM);
+
+		ret = an8801_buckpbus_reg_write(phydev,
+						AN8801_BPBUS_REG_PHY_IRQ_GPIO,
+						val);
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_WAKE_IRQ_EN,
+						   AN8801_IRQ_WAKE_LNKCHG);
+		if (ret)
+			return ret;
+
+	} else {
+		ret = an8801_buckpbus_reg_write(phydev,
+						AN8801_BPBUS_REG_PHY_IRQ_GPIO,
+						0);
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_clear_bits(phydev,
+						     AN8801_BPBUS_REG_WAKE_IRQ_EN,
+						     AN8801_IRQ_WAKE_LNKCHG);
+		if (ret)
+			return ret;
+	}
+
+	ret = an8801r_ack_interrupt(phydev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static irqreturn_t an8801r_handle_interrupt(struct phy_device *phydev)
+{
+	u32 irq_status = 0;
+	int ret;
+
+	ret = an8801_buckpbus_reg_read(phydev, AN8801_BPBUS_REG_WAKE_IRQ_STS,
+				       &irq_status);
+	if (ret)
+		return ret;
+
+	ret = an8801r_ack_interrupt(phydev);
+	if (ret)
+		return IRQ_NONE;
+
+	if (irq_status & AN8801_IRQ_WAKE_MAGICPKT) {
+		pm_wakeup_event(&phydev->mdio.dev, 0);
+		return IRQ_HANDLED;
+	}
+
+	if (irq_status & AN8801_IRQ_WAKE_LNKCHG) {
+		phy_trigger_machine(phydev);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static void an8801r_get_wol(struct phy_device *phydev,
+			    struct ethtool_wolinfo *wol)
+{
+	u32 reg_val;
+
+	/* If the PHY is not capable of waking the system, then WoL can not
+	 * be supported.
+	 */
+	if (!device_can_wakeup(&phydev->mdio.dev)) {
+		wol->supported = 0;
+		return;
+	}
+
+	wol->supported = WAKE_MAGIC;
+
+	an8801_buckpbus_reg_read(phydev, AN8801_BPBUS_REG_WAKEUP_CTL1,
+				 &reg_val);
+
+	if (reg_val & AN8801_WOL_WAKE_MAGIC_EN)
+		wol->wolopts |= WAKE_MAGIC;
+	else
+		wol->wolopts &= ~WAKE_MAGIC;
+}
+
+static int an8801r_set_wol(struct phy_device *phydev,
+			   struct ethtool_wolinfo *wol)
+{
+	struct net_device *attach_dev = phydev->attached_dev;
+	const unsigned char *macaddr = attach_dev->dev_addr;
+	struct an8801r_priv *priv = phydev->priv;
+	u32 reg_val;
+	int ret;
+
+	if (!device_can_wakeup(&phydev->mdio.dev))
+		return -EOPNOTSUPP;
+
+	if (wol->wolopts & WAKE_MAGIC) {
+		/* MAC bits 16..47 */
+		reg_val = (macaddr[2] << 24) | (macaddr[3] << 16);
+		reg_val |= (macaddr[4] << 8) | (macaddr[5]);
+
+		ret = an8801_buckpbus_reg_write(phydev,
+						AN8801_BPBUS_REG_WOL_MAC_16_47,
+						reg_val);
+		if (ret)
+			return ret;
+
+		/* MAC bits 0..15 */
+		reg_val = (macaddr[0] << 8) | (macaddr[1]);
+
+		ret = an8801_buckpbus_reg_write(phydev,
+						AN8801_BPBUS_REG_WOL_MAC_0_15,
+						reg_val);
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_WAKEUP_CTL1,
+						   AN8801_WOL_WAKE_MAGIC_EN);
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_WAKE_IRQ_EN,
+						   AN8801_IRQ_WAKE_MAGICPKT);
+		if (ret)
+			return ret;
+
+	} else {
+		ret = an8801_buckpbus_reg_clear_bits(phydev,
+						     AN8801_BPBUS_REG_WAKEUP_CTL1,
+						     AN8801_WOL_WAKE_MAGIC_EN);
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_clear_bits(phydev,
+						     AN8801_BPBUS_REG_WAKE_IRQ_EN,
+						     AN8801_IRQ_WAKE_MAGICPKT);
+		if (ret)
+			return ret;
+	}
+
+	priv->wake_magic_enabled = !!(wol->wolopts & WAKE_MAGIC);
+
+	device_set_wakeup_enable(&phydev->mdio.dev,
+				 priv->wake_magic_enabled);
+
+	return 0;
+}
+
+static int an8801r_of_init_leds(struct phy_device *phydev, u8 *led_cfg)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *leds;
+	u32 function_enum_idx;
+	int ret;
+
+	if (!np)
+		return 0;
+
+	/* If devicetree is present, leds configuration is required */
+	leds = of_get_child_by_name(np, "leds");
+	if (!leds)
+		return 0;
+
+	for_each_available_child_of_node_scoped(leds, led) {
+		u32 led_idx;
+
+		ret = of_property_read_u32(led, "reg", &led_idx);
+		if (ret)
+			goto out;
+
+		if (led_idx >= AN8801R_NUM_LEDS) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = of_property_read_u32(led, "function-enumerator",
+					   &function_enum_idx);
+		if (ret)
+			function_enum_idx = AN8801R_LED_FN_NONE;
+
+		if (function_enum_idx >= AN8801R_LED_FN_MAX) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		led_cfg[led_idx] = function_enum_idx;
+	}
+out:
+	of_node_put(leds);
+	return ret;
+}
+
+static int an8801r_rgmii_rxdelay(struct phy_device *phydev, bool enable,
+				 u16 delay_steps)
+{
+	u32 reg_val;
+
+	if (delay_steps > RGMII_DELAY_STEP_MASK)
+		return -EINVAL;
+
+	if (enable) {
+		reg_val = delay_steps & RGMII_DELAY_STEP_MASK;
+
+		 /* Set align bit to add extra offset for RX delay */
+		reg_val |= RGMII_RXDELAY_ALIGN;
+
+		 /* Set force mode bit to enable RX delay insertion */
+		reg_val |= RGMII_RXDELAY_FORCE_MODE;
+	} else {
+		reg_val = 0;
+	}
+
+	return an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_RXDLY_STEP,
+					 reg_val);
+}
+
+static int an8801r_rgmii_txdelay(struct phy_device *phydev, bool enable,
+				 u16 delay_steps)
+{
+	u32 reg_val;
+
+	if (delay_steps > RGMII_DELAY_STEP_MASK)
+		return -EINVAL;
+
+	if (enable) {
+		reg_val = delay_steps & RGMII_DELAY_STEP_MASK;
+
+		 /* Set force mode bit to enable TX delay insertion */
+		reg_val |= RGMII_TXDELAY_FORCE_MODE;
+	} else {
+		reg_val = 0;
+	}
+
+	return an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_TXDLY_STEP,
+					 reg_val);
+}
+
+static int an8801r_rgmii_delay_config(struct phy_device *phydev)
+{
+	bool enable_delay;
+	u16 delay_step;
+	int ret;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
+		enable_delay = true;
+		delay_step = AN8801_RGMII_TXDELAY_DEFAULT;
+	} else {
+		enable_delay = false;
+		delay_step = RGMII_DELAY_NO_STEP;
+	}
+
+	ret = an8801r_rgmii_txdelay(phydev, enable_delay, delay_step);
+	if (ret)
+		return ret;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+		enable_delay = true;
+		delay_step = AN8801_RGMII_RXDELAY_DEFAULT;
+	} else {
+		enable_delay = false;
+		delay_step = RGMII_DELAY_NO_STEP;
+	}
+
+	ret = an8801r_rgmii_rxdelay(phydev, enable_delay, delay_step);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int an8801r_config_init(struct phy_device *phydev)
+{
+	u8 led_default_function[AN8801R_NUM_LEDS] = { 0 };
+	int ret;
+
+	ret = an8801r_of_init_leds(phydev, led_default_function);
+	if (ret)
+		return ret;
+
+	/* Disable Low Power Mode (LPM) */
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL0,
+			    FIELD_PREP(AN8801_PHY_INTFUNC_MASK, 0x1e));
+	if (ret)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL1,
+			    FIELD_PREP(AN8801_PHY_INTFUNC_MASK, 0x2));
+	if (ret)
+		return ret;
+
+	/* Set the PHY to perform auto-downshift after 3 auto-negotiation
+	 * attempts
+	 */
+	ret = phy_write_paged(phydev, AIR_PHY_PAGE_EXTENDED_1,
+			      AN8801_EXT_REG_PHY,
+			      FIELD_PREP(AN8801_EXT_PHY_CTRL1, 0x1d) |
+			      FIELD_PREP(AN8801_EXT_PHY_DOWNSHIFT_CTL, 1) |
+			      AN8801_EXT_PHY_DOWNSHIFT_EN);
+	if (ret < 0)
+		return ret;
+
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_BYPASS_PTP,
+					AN8801_BYP_PTP_RGMII_TO_GPHY);
+	if (ret)
+		return ret;
+
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(0),
+					AN8801_EFIFO_RX_EN |
+					AN8801_EFIFO_TX_EN |
+					AN8801_EFIFO_RX_CLK_EN |
+					AN8801_EFIFO_TX_CLK_EN |
+					AN8801_EFIFO_RX_EEE_EN |
+					AN8801_EFIFO_TX_EEE_EN);
+	if (ret)
+		return ret;
+
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(1),
+					AN8801_EFIFO_ALL_EN);
+	if (ret)
+		return ret;
+
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(2),
+					AN8801_EFIFO_ALL_EN);
+	if (ret)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+			    AN8801_PHY_TX_PAIR_DLY_SEL_GBE,
+			    FIELD_PREP(AN8801_PHY_PAIR_DLY_SEL_A_GBE, 4) |
+			    FIELD_PREP(AN8801_PHY_PAIR_DLY_SEL_C_GBE, 4));
+	if (ret)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8801_PHY_RXADC_CTRL,
+			    AN8801_PHY_RXADC_SAMP_PHSEL_A |
+			    AN8801_PHY_RXADC_SAMP_PHSEL_C);
+	if (ret)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8801_PHY_RXADC_REV_0,
+			    FIELD_PREP(AN8801_PHY_RXADC_REV_MASK_A, 1));
+	if (ret)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8801_PHY_RXADC_REV_1,
+			    FIELD_PREP(AN8801_PHY_RXADC_REV_MASK_C, 1));
+	if (ret)
+		return ret;
+
+	ret = an8801r_rgmii_delay_config(phydev);
+	if (ret)
+		return ret;
+
+	ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_CKO,
+					AN8801_CKO_OUTPUT_MODE_AUTO);
+	if (ret)
+		return ret;
+
+	ret = an8801r_led_init(phydev, led_default_function);
+	if (ret) {
+		phydev_err(phydev, "Cannot initialize LEDs: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int an8801r_read_status(struct phy_device *phydev)
+{
+	int prev_speed, ret;
+	u32 val;
+
+	prev_speed = phydev->speed;
+
+	ret = genphy_read_status(phydev);
+	if (ret)
+		return ret;
+
+	if (phydev->link && prev_speed != phydev->speed) {
+		val = phydev->speed == SPEED_1000 ?
+		      AN8801_BPBUS_LINK_MODE_1000 : 0;
+
+		return an8801_buckpbus_reg_rmw(phydev,
+					       AN8801_BPBUS_REG_LINK_MODE,
+					       AN8801_BPBUS_LINK_MODE_1000,
+					       val);
+	};
+
+	return 0;
+}
+
+static int an8801r_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct an8801r_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->wake_lnkchg_enabled = true;
+
+	phydev->priv = priv;
+
+	/* Mark this PHY as wakeup capable and register the interrupt as a
+	 * wakeup IRQ if the PHY is marked as a wakeup source in devicetree,
+	 * and the interrupt is valid.
+	 */
+	if (of_property_read_bool(dev->of_node, "wakeup-source") &&
+	    phy_interrupt_is_valid(phydev)) {
+		device_set_wakeup_capable(dev, true);
+		devm_pm_set_wake_irq(dev, phydev->irq);
+	}
+
+	return 0;
+}
+
+static int an8801r_suspend(struct phy_device *phydev)
+{
+	struct an8801r_priv *priv = phydev->priv;
+	int ret;
+
+	/* If the PHY may wake up by a wake-on-line event, disable the link
+	 * interrupt to only keep the  WOL magic interrupt enabled
+	 */
+	if (device_may_wakeup(&phydev->mdio.dev)) {
+		priv->wake_lnkchg_enabled = false;
+
+		ret = an8801_buckpbus_reg_clear_bits(phydev,
+						     AN8801_BPBUS_REG_WAKE_IRQ_EN,
+						     AN8801_IRQ_WAKE_LNKCHG);
+		if (ret)
+			return ret;
+
+		/* Reset Wol status */
+		ret = an8801r_reset_wake(phydev);
+		if (ret)
+			return ret;
+	}
+
+	if (!phydev->wol_enabled)
+		return genphy_suspend(phydev);
+
+	return 0;
+}
+
+static int an8801r_resume(struct phy_device *phydev)
+{
+	struct an8801r_priv *priv = phydev->priv;
+	int ret;
+
+	ret = genphy_resume(phydev);
+	if (ret)
+		return ret;
+
+	/* Restore the interrupt enable so phylib can receive link
+	 * state interrupts.
+	 */
+	if (device_may_wakeup(&phydev->mdio.dev)) {
+		priv->wake_lnkchg_enabled = true;
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_WAKEUP_CTL1,
+						   AN8801_WOL_WAKE_LNKCHG_EN);
+		if (ret)
+			return ret;
+
+		ret = an8801_buckpbus_reg_set_bits(phydev,
+						   AN8801_BPBUS_REG_WAKE_IRQ_EN,
+						   AN8801_IRQ_WAKE_LNKCHG);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static struct phy_driver airoha_driver[] = {
+{
+	PHY_ID_MATCH_MODEL(AN8801R_PHY_ID),
+	.name			= "Airoha AN8801R",
+	.probe			= an8801r_probe,
+	.config_init		= an8801r_config_init,
+	.suspend		= an8801r_suspend,
+	.resume			= an8801r_resume,
+	.config_aneg		= genphy_config_aneg,
+	.read_status		= an8801r_read_status,
+	.config_intr		= an8801r_config_intr,
+	.handle_interrupt	= an8801r_handle_interrupt,
+	.set_wol		= an8801r_set_wol,
+	.get_wol		= an8801r_get_wol,
+	.read_page		= air_phy_read_page,
+	.write_page		= air_phy_write_page,
+	.flags			= PHY_ALWAYS_CALL_SUSPEND,
+	.led_brightness_set	= an8801r_led_brightness_set,
+	.led_blink_set		= an8801r_led_blink_set,
+	.led_hw_is_supported	= an8801r_led_hw_is_supported,
+	.led_hw_control_set	= an8801r_led_hw_control_set,
+	.led_hw_control_get	= an8801r_led_hw_control_get,
+	.led_polarity_set	= an8801r_led_polarity_set,
+} };
+module_phy_driver(airoha_driver);
+
+static struct mdio_device_id __maybe_unused an8801_tbl[] = {
+	{ PHY_ID_MATCH_MODEL(AN8801R_PHY_ID) },
+	{ }
+};
+MODULE_DEVICE_TABLE(mdio, an8801_tbl);
+
+MODULE_DESCRIPTION("Airoha AN8801 PHY driver");
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_LICENSE("GPL");

-- 
2.53.0



^ permalink raw reply related

* [PATCH net-next v2 3/4] net: phy: air_phy_lib: Factorize BuckPBus register accessors
From: Louis-Alexis Eyraud @ 2026-03-26 12:04 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Andrew Lunn, Heiner Kallweit,
	Russell King
  Cc: kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	Louis-Alexis Eyraud
In-Reply-To: <20260326-add-airoha-an8801-support-v2-0-1a42d6b6050f@collabora.com>

In preparation of Airoha AN8801R PHY support, move the BuckPBus
register accessors and definitions, present in air_en8811h driver,
into the Airoha PHY shared code (air_phy_lib), so they will be usable
by the new driver without duplicating them.
Also, update air_en8811h driver to use the new function names.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 drivers/net/phy/air_en8811h.c | 303 ++++++++----------------------------------
 drivers/net/phy/air_phy_lib.c | 180 +++++++++++++++++++++++++
 drivers/net/phy/air_phy_lib.h |  23 ++++
 3 files changed, 259 insertions(+), 247 deletions(-)

diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c
index be7c3426182a26fe3799b875827750e7772caadd..a42898ae41358fe86072a55528a0ecff0eb5ec19 100644
--- a/drivers/net/phy/air_en8811h.c
+++ b/drivers/net/phy/air_en8811h.c
@@ -42,22 +42,6 @@
 #define   AIR_AUX_CTRL_STATUS_SPEED_1000	0x8
 #define   AIR_AUX_CTRL_STATUS_SPEED_2500	0xc
 
-#define   AIR_PHY_PAGE_STANDARD			0x0000
-#define   AIR_PHY_PAGE_EXTENDED_4		0x0004
-
-/* MII Registers Page 4*/
-#define AIR_BPBUS_MODE			0x10
-#define   AIR_BPBUS_MODE_ADDR_FIXED		0x0000
-#define   AIR_BPBUS_MODE_ADDR_INCR		BIT(15)
-#define AIR_BPBUS_WR_ADDR_HIGH		0x11
-#define AIR_BPBUS_WR_ADDR_LOW		0x12
-#define AIR_BPBUS_WR_DATA_HIGH		0x13
-#define AIR_BPBUS_WR_DATA_LOW		0x14
-#define AIR_BPBUS_RD_ADDR_HIGH		0x15
-#define AIR_BPBUS_RD_ADDR_LOW		0x16
-#define AIR_BPBUS_RD_DATA_HIGH		0x17
-#define AIR_BPBUS_RD_DATA_LOW		0x18
-
 /* Registers on MDIO_MMD_VEND1 */
 #define EN8811H_PHY_FW_STATUS		0x8009
 #define   EN8811H_PHY_READY			0x02
@@ -245,183 +229,6 @@ static const unsigned long en8811h_led_trig = BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
 					      BIT(TRIGGER_NETDEV_RX)          |
 					      BIT(TRIGGER_NETDEV_TX);
 
-static int __air_buckpbus_reg_write(struct phy_device *phydev,
-				    u32 pbus_address, u32 pbus_data)
-{
-	int ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
-			  upper_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
-			  lower_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH,
-			  upper_16_bits(pbus_data));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW,
-			  lower_16_bits(pbus_data));
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int air_buckpbus_reg_write(struct phy_device *phydev,
-				  u32 pbus_address, u32 pbus_data)
-{
-	int saved_page;
-	int ret = 0;
-
-	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
-
-	if (saved_page >= 0) {
-		ret = __air_buckpbus_reg_write(phydev, pbus_address,
-					       pbus_data);
-		if (ret < 0)
-			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
-				   pbus_address, ret);
-	}
-
-	return phy_restore_page(phydev, saved_page, ret);
-}
-
-static int __air_buckpbus_reg_read(struct phy_device *phydev,
-				   u32 pbus_address, u32 *pbus_data)
-{
-	int pbus_data_low, pbus_data_high;
-	int ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH,
-			  upper_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW,
-			  lower_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH);
-	if (pbus_data_high < 0)
-		return pbus_data_high;
-
-	pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW);
-	if (pbus_data_low < 0)
-		return pbus_data_low;
-
-	*pbus_data = pbus_data_low | (pbus_data_high << 16);
-	return 0;
-}
-
-static int air_buckpbus_reg_read(struct phy_device *phydev,
-				 u32 pbus_address, u32 *pbus_data)
-{
-	int saved_page;
-	int ret = 0;
-
-	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
-
-	if (saved_page >= 0) {
-		ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data);
-		if (ret < 0)
-			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
-				   pbus_address, ret);
-	}
-
-	return phy_restore_page(phydev, saved_page, ret);
-}
-
-static int __air_buckpbus_reg_modify(struct phy_device *phydev,
-				     u32 pbus_address, u32 mask, u32 set)
-{
-	int pbus_data_low, pbus_data_high;
-	u32 pbus_data_old, pbus_data_new;
-	int ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH,
-			  upper_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW,
-			  lower_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH);
-	if (pbus_data_high < 0)
-		return pbus_data_high;
-
-	pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW);
-	if (pbus_data_low < 0)
-		return pbus_data_low;
-
-	pbus_data_old = pbus_data_low | (pbus_data_high << 16);
-	pbus_data_new = (pbus_data_old & ~mask) | set;
-	if (pbus_data_new == pbus_data_old)
-		return 0;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
-			  upper_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
-			  lower_16_bits(pbus_address));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH,
-			  upper_16_bits(pbus_data_new));
-	if (ret < 0)
-		return ret;
-
-	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW,
-			  lower_16_bits(pbus_data_new));
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int air_buckpbus_reg_modify(struct phy_device *phydev,
-				   u32 pbus_address, u32 mask, u32 set)
-{
-	int saved_page;
-	int ret = 0;
-
-	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
-
-	if (saved_page >= 0) {
-		ret = __air_buckpbus_reg_modify(phydev, pbus_address, mask,
-						set);
-		if (ret < 0)
-			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
-				   pbus_address, ret);
-	}
-
-	return phy_restore_page(phydev, saved_page, ret);
-}
-
 static int __air_write_buf(struct phy_device *phydev, u32 address,
 			   const struct firmware *fw)
 {
@@ -480,8 +287,8 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev)
 {
 	int ret, reg_value;
 
-	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
-				     EN8811H_FW_CTRL_1_FINISH);
+	ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+					 EN8811H_FW_CTRL_1_FINISH);
 	if (ret)
 		return ret;
 
@@ -506,28 +313,29 @@ static int an8811hb_check_crc(struct phy_device *phydev, u32 set1,
 	int ret;
 
 	/* Configure CRC */
-	ret = air_buckpbus_reg_modify(phydev, set1,
-				      AN8811HB_CRC_RD_EN,
-				      AN8811HB_CRC_RD_EN);
+	ret = air_phy_buckpbus_reg_modify(phydev, set1,
+					  AN8811HB_CRC_RD_EN,
+					  AN8811HB_CRC_RD_EN);
 	if (ret < 0)
 		return ret;
-	air_buckpbus_reg_read(phydev, set1, &pbus_value);
+	air_phy_buckpbus_reg_read(phydev, set1, &pbus_value);
 
 	do {
 		msleep(300);
-		air_buckpbus_reg_read(phydev, mon2, &pbus_value);
+		air_phy_buckpbus_reg_read(phydev, mon2, &pbus_value);
 
 		/* We do not know what errors this check is supposed
 		 * catch or what to do about a failure. So print the
 		 * result and continue like the vendor driver does.
 		 */
 		if (pbus_value & AN8811HB_CRC_ST) {
-			air_buckpbus_reg_read(phydev, mon3, &pbus_value);
+			air_phy_buckpbus_reg_read(phydev, mon3, &pbus_value);
 			phydev_dbg(phydev, "CRC Check %s!\n",
 				   pbus_value & AN8811HB_CRC_CHECK_PASS ?
 					"PASS" : "FAIL");
-			return air_buckpbus_reg_modify(phydev, set1,
-						       AN8811HB_CRC_RD_EN, 0);
+			return air_phy_buckpbus_reg_modify(phydev, set1,
+							   AN8811HB_CRC_RD_EN,
+							   0);
 		}
 	} while (--retry);
 
@@ -539,8 +347,8 @@ static void en8811h_print_fw_version(struct phy_device *phydev)
 {
 	struct en8811h_priv *priv = phydev->priv;
 
-	air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,
-			      &priv->firmware_version);
+	air_phy_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,
+				  &priv->firmware_version);
 	phydev_info(phydev, "MD32 firmware version: %08x\n",
 		    priv->firmware_version);
 }
@@ -565,8 +373,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)
 {
 	int ret;
 
-	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
-				     EN8811H_FW_CTRL_1_START);
+	ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+					 EN8811H_FW_CTRL_1_START);
 	if (ret < 0)
 		return ret;
 
@@ -607,14 +415,14 @@ static int en8811h_load_firmware(struct phy_device *phydev)
 	if (ret < 0)
 		goto en8811h_load_firmware_rel1;
 
-	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
-				     EN8811H_FW_CTRL_1_START);
+	ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+					 EN8811H_FW_CTRL_1_START);
 	if (ret < 0)
 		goto en8811h_load_firmware_out;
 
-	ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
-				      EN8811H_FW_CTRL_2_LOADING,
-				      EN8811H_FW_CTRL_2_LOADING);
+	ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
+					  EN8811H_FW_CTRL_2_LOADING,
+					  EN8811H_FW_CTRL_2_LOADING);
 	if (ret < 0)
 		goto en8811h_load_firmware_out;
 
@@ -626,8 +434,8 @@ static int en8811h_load_firmware(struct phy_device *phydev)
 	if (ret < 0)
 		goto en8811h_load_firmware_out;
 
-	ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
-				      EN8811H_FW_CTRL_2_LOADING, 0);
+	ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
+					  EN8811H_FW_CTRL_2_LOADING, 0);
 	if (ret < 0)
 		goto en8811h_load_firmware_out;
 
@@ -653,8 +461,8 @@ static int en8811h_restart_mcu(struct phy_device *phydev)
 {
 	int ret;
 
-	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
-				     EN8811H_FW_CTRL_1_START);
+	ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+					 EN8811H_FW_CTRL_1_START);
 	if (ret < 0)
 		return ret;
 
@@ -948,7 +756,7 @@ static unsigned long an8811hb_clk_recalc_rate(struct clk_hw *hw,
 	u32 pbus_value;
 	int ret;
 
-	ret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);
+	ret = air_phy_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);
 	if (ret < 0)
 		return ret;
 
@@ -960,9 +768,9 @@ static int an8811hb_clk_enable(struct clk_hw *hw)
 	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 	struct phy_device *phydev = priv->phydev;
 
-	return air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,
-				       AN8811HB_CLK_DRV_CKO_MASK,
-				       AN8811HB_CLK_DRV_CKO_MASK);
+	return air_phy_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,
+					   AN8811HB_CLK_DRV_CKO_MASK,
+					   AN8811HB_CLK_DRV_CKO_MASK);
 }
 
 static void an8811hb_clk_disable(struct clk_hw *hw)
@@ -970,8 +778,8 @@ static void an8811hb_clk_disable(struct clk_hw *hw)
 	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 	struct phy_device *phydev = priv->phydev;
 
-	air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,
-				AN8811HB_CLK_DRV_CKO_MASK, 0);
+	air_phy_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,
+				    AN8811HB_CLK_DRV_CKO_MASK, 0);
 }
 
 static int an8811hb_clk_is_enabled(struct clk_hw *hw)
@@ -981,7 +789,7 @@ static int an8811hb_clk_is_enabled(struct clk_hw *hw)
 	u32 pbus_value;
 	int ret;
 
-	ret = air_buckpbus_reg_read(phydev, AN8811HB_CLK_DRV, &pbus_value);
+	ret = air_phy_buckpbus_reg_read(phydev, AN8811HB_CLK_DRV, &pbus_value);
 	if (ret < 0)
 		return ret;
 
@@ -1047,7 +855,7 @@ static unsigned long en8811h_clk_recalc_rate(struct clk_hw *hw,
 	u32 pbus_value;
 	int ret;
 
-	ret = air_buckpbus_reg_read(phydev, EN8811H_HWTRAP1, &pbus_value);
+	ret = air_phy_buckpbus_reg_read(phydev, EN8811H_HWTRAP1, &pbus_value);
 	if (ret < 0)
 		return ret;
 
@@ -1059,9 +867,9 @@ static int en8811h_clk_enable(struct clk_hw *hw)
 	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 	struct phy_device *phydev = priv->phydev;
 
-	return air_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM,
-				       EN8811H_CLK_CGM_CKO,
-				       EN8811H_CLK_CGM_CKO);
+	return air_phy_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM,
+					   EN8811H_CLK_CGM_CKO,
+					   EN8811H_CLK_CGM_CKO);
 }
 
 static void en8811h_clk_disable(struct clk_hw *hw)
@@ -1069,8 +877,8 @@ static void en8811h_clk_disable(struct clk_hw *hw)
 	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 	struct phy_device *phydev = priv->phydev;
 
-	air_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM,
-				EN8811H_CLK_CGM_CKO, 0);
+	air_phy_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM,
+				    EN8811H_CLK_CGM_CKO, 0);
 }
 
 static int en8811h_clk_is_enabled(struct clk_hw *hw)
@@ -1080,7 +888,7 @@ static int en8811h_clk_is_enabled(struct clk_hw *hw)
 	u32 pbus_value;
 	int ret;
 
-	ret = air_buckpbus_reg_read(phydev, EN8811H_CLK_CGM, &pbus_value);
+	ret = air_phy_buckpbus_reg_read(phydev, EN8811H_CLK_CGM, &pbus_value);
 	if (ret < 0)
 		return ret;
 
@@ -1191,9 +999,9 @@ static int an8811hb_probe(struct phy_device *phydev)
 		return ret;
 
 	/* Configure led gpio pins as output */
-	ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
-				      AN8811HB_GPIO_OUTPUT_345,
-				      AN8811HB_GPIO_OUTPUT_345);
+	ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
+					  AN8811HB_GPIO_OUTPUT_345,
+					  AN8811HB_GPIO_OUTPUT_345);
 	if (ret < 0)
 		return ret;
 
@@ -1232,9 +1040,9 @@ static int en8811h_probe(struct phy_device *phydev)
 		return ret;
 
 	/* Configure led gpio pins as output */
-	ret = air_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT,
-				      EN8811H_GPIO_OUTPUT_345,
-				      EN8811H_GPIO_OUTPUT_345);
+	ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT,
+					  EN8811H_GPIO_OUTPUT_345,
+					  EN8811H_GPIO_OUTPUT_345);
 	if (ret < 0)
 		return ret;
 
@@ -1254,9 +1062,9 @@ static int an8811hb_config_serdes_polarity(struct phy_device *phydev)
 		return ret;
 	if (pol == PHY_POL_NORMAL)
 		pbus_value |= AN8811HB_RX_POLARITY_NORMAL;
-	ret = air_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,
-				      AN8811HB_RX_POLARITY_NORMAL,
-				      pbus_value);
+	ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,
+					  AN8811HB_RX_POLARITY_NORMAL,
+					  pbus_value);
 	if (ret < 0)
 		return ret;
 
@@ -1267,9 +1075,9 @@ static int an8811hb_config_serdes_polarity(struct phy_device *phydev)
 	pbus_value = 0;
 	if (pol == PHY_POL_NORMAL)
 		pbus_value |= AN8811HB_TX_POLARITY_NORMAL;
-	return air_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,
-				       AN8811HB_TX_POLARITY_NORMAL,
-				       pbus_value);
+	return air_phy_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,
+					   AN8811HB_TX_POLARITY_NORMAL,
+					   pbus_value);
 }
 
 static int en8811h_config_serdes_polarity(struct phy_device *phydev)
@@ -1303,9 +1111,10 @@ static int en8811h_config_serdes_polarity(struct phy_device *phydev)
 	if (pol == PHY_POL_NORMAL)
 		pbus_value |= EN8811H_POLARITY_TX_NORMAL;
 
-	return air_buckpbus_reg_modify(phydev, EN8811H_POLARITY,
-				       EN8811H_POLARITY_RX_REVERSE |
-				       EN8811H_POLARITY_TX_NORMAL, pbus_value);
+	return air_phy_buckpbus_reg_modify(phydev, EN8811H_POLARITY,
+					   EN8811H_POLARITY_RX_REVERSE |
+					   EN8811H_POLARITY_TX_NORMAL,
+					   pbus_value);
 }
 
 static int an8811hb_config_init(struct phy_device *phydev)
@@ -1457,8 +1266,8 @@ static int en8811h_read_status(struct phy_device *phydev)
 				 val & MDIO_AN_10GBT_STAT_LP2_5G);
 	} else {
 		/* Get link partner 2.5GBASE-T ability from vendor register */
-		ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA,
-					    &pbus_value);
+		ret = air_phy_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA,
+						&pbus_value);
 		if (ret < 0)
 			return ret;
 		linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
diff --git a/drivers/net/phy/air_phy_lib.c b/drivers/net/phy/air_phy_lib.c
index 04c4719a073f98ef75eabd54c4851f6a16391350..780ce2a17d3a58d5e3105534e9fea71bf3097b36 100644
--- a/drivers/net/phy/air_phy_lib.c
+++ b/drivers/net/phy/air_phy_lib.c
@@ -13,6 +13,186 @@
 
 #define AIR_EXT_PAGE_ACCESS		0x1f
 
+static int __air_buckpbus_reg_read(struct phy_device *phydev,
+				   u32 pbus_address, u32 *pbus_data)
+{
+	int pbus_data_low, pbus_data_high;
+	int ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH,
+			  upper_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW,
+			  lower_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH);
+	if (pbus_data_high < 0)
+		return pbus_data_high;
+
+	pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW);
+	if (pbus_data_low < 0)
+		return pbus_data_low;
+
+	*pbus_data = pbus_data_low | (pbus_data_high << 16);
+	return 0;
+}
+
+static int __air_buckpbus_reg_write(struct phy_device *phydev,
+				    u32 pbus_address, u32 pbus_data)
+{
+	int ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
+			  upper_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
+			  lower_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH,
+			  upper_16_bits(pbus_data));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW,
+			  lower_16_bits(pbus_data));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int __air_buckpbus_reg_modify(struct phy_device *phydev,
+				     u32 pbus_address, u32 mask, u32 set)
+{
+	int pbus_data_low, pbus_data_high;
+	u32 pbus_data_old, pbus_data_new;
+	int ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH,
+			  upper_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW,
+			  lower_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH);
+	if (pbus_data_high < 0)
+		return pbus_data_high;
+
+	pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW);
+	if (pbus_data_low < 0)
+		return pbus_data_low;
+
+	pbus_data_old = pbus_data_low | (pbus_data_high << 16);
+	pbus_data_new = (pbus_data_old & ~mask) | set;
+	if (pbus_data_new == pbus_data_old)
+		return 0;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
+			  upper_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
+			  lower_16_bits(pbus_address));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH,
+			  upper_16_bits(pbus_data_new));
+	if (ret < 0)
+		return ret;
+
+	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW,
+			  lower_16_bits(pbus_data_new));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address,
+			      u32 *pbus_data)
+{
+	int saved_page;
+	int ret = 0;
+
+	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
+
+	if (saved_page >= 0) {
+		ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data);
+		if (ret < 0)
+			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
+				   pbus_address, ret);
+	}
+
+	return phy_restore_page(phydev, saved_page, ret);
+}
+EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_read);
+
+int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address,
+			       u32 pbus_data)
+{
+	int saved_page;
+	int ret = 0;
+
+	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
+
+	if (saved_page >= 0) {
+		ret = __air_buckpbus_reg_write(phydev, pbus_address,
+					       pbus_data);
+		if (ret < 0)
+			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
+				   pbus_address, ret);
+	}
+
+	return phy_restore_page(phydev, saved_page, ret);
+}
+EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_write);
+
+int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address,
+				u32 mask, u32 set)
+{
+	int saved_page;
+	int ret = 0;
+
+	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
+
+	if (saved_page >= 0) {
+		ret = __air_buckpbus_reg_modify(phydev, pbus_address, mask,
+						set);
+		if (ret < 0)
+			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
+				   pbus_address, ret);
+	}
+
+	return phy_restore_page(phydev, saved_page, ret);
+}
+EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_modify);
+
 int air_phy_read_page(struct phy_device *phydev)
 {
 	return __phy_read(phydev, AIR_EXT_PAGE_ACCESS);
diff --git a/drivers/net/phy/air_phy_lib.h b/drivers/net/phy/air_phy_lib.h
index dd501b175a3a38e57744f79571eb1bc4ef46fdf5..23d8e3e318398958f2bba297619f35a86f9871a9 100644
--- a/drivers/net/phy/air_phy_lib.h
+++ b/drivers/net/phy/air_phy_lib.h
@@ -8,6 +8,29 @@
 #ifndef __AIR_PHY_LIB_H
 #define __AIR_PHY_LIB_H
 
+#define AIR_PHY_PAGE_STANDARD		0x0000
+#define AIR_PHY_PAGE_EXTENDED_1		0x0001
+#define AIR_PHY_PAGE_EXTENDED_4		0x0004
+
+/* MII Registers Page 4*/
+#define AIR_BPBUS_MODE			0x10
+#define   AIR_BPBUS_MODE_ADDR_FIXED		0x0000
+#define   AIR_BPBUS_MODE_ADDR_INCR		BIT(15)
+#define AIR_BPBUS_WR_ADDR_HIGH		0x11
+#define AIR_BPBUS_WR_ADDR_LOW		0x12
+#define AIR_BPBUS_WR_DATA_HIGH		0x13
+#define AIR_BPBUS_WR_DATA_LOW		0x14
+#define AIR_BPBUS_RD_ADDR_HIGH		0x15
+#define AIR_BPBUS_RD_ADDR_LOW		0x16
+#define AIR_BPBUS_RD_DATA_HIGH		0x17
+#define AIR_BPBUS_RD_DATA_LOW		0x18
+
+int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address,
+				u32 mask, u32 set);
+int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address,
+			      u32 *pbus_data);
+int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address,
+			       u32 pbus_data);
 int air_phy_read_page(struct phy_device *phydev);
 int air_phy_write_page(struct phy_device *phydev, int page);
 

-- 
2.53.0



^ permalink raw reply related

* [PATCH net-next v2 0/4] Introduce Airoha AN8801R series Gigabit Ethernet PHY driver
From: Louis-Alexis Eyraud @ 2026-03-26 12:04 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Andrew Lunn, Heiner Kallweit,
	Russell King
  Cc: kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	Louis-Alexis Eyraud

This series introduces the Airoha AN8801R Gigabit Ethernet PHY initial
support.

The Airoha AN8801R is a low power single-port Ethernet PHY Transceiver
with Single-port serdes interface for 1000Base-X/RGMII.
This chip is compliant with 10Base-T, 100Base-TX and 1000Base-T IEEE
802.3(u,ab) and supports:
  - Energy Efficient Ethernet (802.3az)
  - Full Duplex Control Flow (802.3x)
  - auto-negotiation
  - crossover detect and autocorrection,
  - Wake-on-LAN with Magic Packet
  - Jumbo Frame up to 9 Kilobytes.
This PHY also supports up to three user-configurable LEDs, which are
usually used for LAN Activity, 100M, 1000M indication.

The series provides the devicetree binding and the driver that have been
written by AngeloGioacchino Del Regno, based on downstream
implementation ([1]). The driver allows setting up PHY LEDs, 10/100M,
1000M speeds, and Wake on LAN and PHY interrupts.

Since v2, the series also adds the air_phy_lib library, which goal is to
share common code between air_en8811h and air_an8801 drivers, and its use
in them. The first shared functions are the existing BuckPbus register
accessors and air_phy_read/write_page functions coming from air_en8811h
driver.

The series is based on net-next kernel tree (sha1: d1e59a4697371) and
I have tested it on Mediatek Genio 720-EVK board (that integrates an
Airoha AN8801RIN/A Ethernet PHY) with early board hardware enablement
patches.

[1]: https://gitlab.com/mediatek/aiot/bsp/linux/-/blob/mtk-v6.6/drivers/net/phy/an8801.c

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
Changes in v2:
- Rebased on net-next (d1e59a4697371)
- Fixed dt-bindings to remove the leds property from the required ones and
  add wakeup-source as valid property
- Added new reviewed-by trailer for dt_bindings
- Added new patches (2 and 3) to create air_phy_lib, to share common code
  between air_en8811h and air_an8801 drivers and use it in air_en8811h.
- Remove custom BuckPBus register accessor functions and definitions from
  air_an8801 and use the ones from air_phy_lib. It also fixes a build
  issue on v1 due to an uninitialized variable used in
  __air_buckpbus_reg_read, that is now removed from driver code
- Added air_an8801_probe function to allocate the newly added private
  data structure and detect if the PHY is wakeup capable and the interrupt
  can be registered as a wakeup IRQ, and perform the needed actions
- Added an8801r_suspend and an8801r_resume functions to perform specific
  actions when WoL is enabled (reset its status, enable/disable the Link
  Changed interrupt) and call the genphy_suspend/resume functions if
  needed
- Modified an8801r_get_wol to return WoL is not supported if the PHY
  device is not wakeup capable
- Modified an8801r_set_wol to return EOPNOTSUPP error code if the PHY
  device is not wakeup capable, and to update the wakeup flag according
  to WoL mode
- Modified an8801r_config_init to remove EEE disabling and replace
  __phy_write use by phy_write_paged
- Reworked an8801r_rgmii_delay_config and its subfunctions to fix a
  double return use in PHY_INTERFACE_MODE_RGMII_ID case, replace the
  magic value use for default TX and RX delay and handle better the
  enable/disable the inserted delays for all RGMII modes
- Merged an8801r_did_interrupt function in an8801r_handle_interrupt
- Modified the an8801r_handle_interrupt processing to process differently
  the Magic Packet (to notify system wakeup) and the Link Changed
  interrupt (to notify PHY state machine)
- Splitted the reset WoL status part from an8801r_ack_interrupt and fix
  an issue that in some random cases made WAKEUP_CTL1 register lose the
  Magic Packet WoL settings
- Modified an8801r_of_init_leds function so it does not return an error
  if the leds configuration is not present in devicetree
- Removed feature field and add PHY_ALWAYS_CALL_SUSPEND flag in
  airoha_driver data structure

- Link to v1: https://lore.kernel.org/r/20260304-add-airoha-an8801-support-v1-0-0ae4ee5a2f9d@collabora.com

---
AngeloGioacchino Del Regno (2):
      dt-bindings: net: Add support for Airoha AN8801/R GbE PHY
      net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver

Louis-Alexis Eyraud (2):
      net: phy: Add Airoha phy library for shared code
      net: phy: air_phy_lib: Factorize BuckPBus register accessors

 .../devicetree/bindings/net/airoha,an8801.yaml     |   85 ++
 drivers/net/phy/Kconfig                            |   12 +
 drivers/net/phy/Makefile                           |    2 +
 drivers/net/phy/air_an8801.c                       | 1115 ++++++++++++++++++++
 drivers/net/phy/air_en8811h.c                      |  316 +-----
 drivers/net/phy/air_phy_lib.c                      |  210 ++++
 drivers/net/phy/air_phy_lib.h                      |   37 +
 7 files changed, 1519 insertions(+), 258 deletions(-)
---
base-commit: d1e59a46973719e458bec78d00dd767d7a7ba71f
change-id: 20260303-add-airoha-an8801-support-57d544a4afed

Best regards,
-- 
Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>



^ permalink raw reply

* [PATCH net-next v2 2/4] net: phy: Add Airoha phy library for shared code
From: Louis-Alexis Eyraud @ 2026-03-26 12:04 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Andrew Lunn, Heiner Kallweit,
	Russell King
  Cc: kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	Louis-Alexis Eyraud
In-Reply-To: <20260326-add-airoha-an8801-support-v2-0-1a42d6b6050f@collabora.com>

In preparation of Airoha AN8801R PHY support, split out the interface
functions that will be common between the already present air_en8811h
driver and the new one, and put them into a new library named
air_phy_lib.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 drivers/net/phy/Kconfig       |  6 ++++++
 drivers/net/phy/Makefile      |  1 +
 drivers/net/phy/air_en8811h.c | 13 ++-----------
 drivers/net/phy/air_phy_lib.c | 30 ++++++++++++++++++++++++++++++
 drivers/net/phy/air_phy_lib.h | 14 ++++++++++++++
 5 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index b5ee338b620d53980fbec9e83ab0de3d96ab4cc9..b6b1cde7e51fa1e470bfe210c8764a193449acb5 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -92,10 +92,16 @@ config AS21XXX_PHY
 
 config AIR_EN8811H_PHY
 	tristate "Airoha EN8811H 2.5 Gigabit PHY"
+	select AIR_NET_PHYLIB
 	select PHY_COMMON_PROPS
 	help
 	  Currently supports the Airoha EN8811H PHY.
 
+config AIR_NET_PHYLIB
+	tristate
+	help
+	  Airoha Ethernet PHY common library
+
 config AMD_PHY
 	tristate "AMD and Altima PHYs"
 	help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 05e4878af27abeae3dfd9ab18fd29f8bf788b2a4..7cf1fa9e12cb6073a9e68c0ffa6284b361b80487 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -30,6 +30,7 @@ obj-y				+= $(sfp-obj-y) $(sfp-obj-m)
 obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
 obj-$(CONFIG_AIR_EN8811H_PHY)   += air_en8811h.o
+obj-$(CONFIG_AIR_NET_PHYLIB)	+= air_phy_lib.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_AMCC_QT2025_PHY)	+= qt2025.o
 obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia/
diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c
index 29ae73e65caaa9cdebe2253b5349aa6c7478dc85..be7c3426182a26fe3799b875827750e7772caadd 100644
--- a/drivers/net/phy/air_en8811h.c
+++ b/drivers/net/phy/air_en8811h.c
@@ -21,6 +21,8 @@
 #include <linux/wordpart.h>
 #include <linux/unaligned.h>
 
+#include "air_phy_lib.h"
+
 #define EN8811H_PHY_ID		0x03a2a411
 #define AN8811HB_PHY_ID		0xc0ff04a0
 
@@ -40,7 +42,6 @@
 #define   AIR_AUX_CTRL_STATUS_SPEED_1000	0x8
 #define   AIR_AUX_CTRL_STATUS_SPEED_2500	0xc
 
-#define AIR_EXT_PAGE_ACCESS		0x1f
 #define   AIR_PHY_PAGE_STANDARD			0x0000
 #define   AIR_PHY_PAGE_EXTENDED_4		0x0004
 
@@ -244,16 +245,6 @@ static const unsigned long en8811h_led_trig = BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
 					      BIT(TRIGGER_NETDEV_RX)          |
 					      BIT(TRIGGER_NETDEV_TX);
 
-static int air_phy_read_page(struct phy_device *phydev)
-{
-	return __phy_read(phydev, AIR_EXT_PAGE_ACCESS);
-}
-
-static int air_phy_write_page(struct phy_device *phydev, int page)
-{
-	return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page);
-}
-
 static int __air_buckpbus_reg_write(struct phy_device *phydev,
 				    u32 pbus_address, u32 pbus_data)
 {
diff --git a/drivers/net/phy/air_phy_lib.c b/drivers/net/phy/air_phy_lib.c
new file mode 100644
index 0000000000000000000000000000000000000000..04c4719a073f98ef75eabd54c4851f6a16391350
--- /dev/null
+++ b/drivers/net/phy/air_phy_lib.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Airoha Ethernet PHY common library
+ *
+ * Copyright (C) 2026 Airoha Technology Corp.
+ * Copyright (C) 2026 Collabora Ltd.
+ *                    Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/phy.h>
+
+#include "air_phy_lib.h"
+
+#define AIR_EXT_PAGE_ACCESS		0x1f
+
+int air_phy_read_page(struct phy_device *phydev)
+{
+	return __phy_read(phydev, AIR_EXT_PAGE_ACCESS);
+}
+EXPORT_SYMBOL_GPL(air_phy_read_page);
+
+int air_phy_write_page(struct phy_device *phydev, int page)
+{
+	return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page);
+}
+EXPORT_SYMBOL_GPL(air_phy_write_page);
+
+MODULE_DESCRIPTION("Airoha PHY Library");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Louis-Alexis Eyraud");
diff --git a/drivers/net/phy/air_phy_lib.h b/drivers/net/phy/air_phy_lib.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd501b175a3a38e57744f79571eb1bc4ef46fdf5
--- /dev/null
+++ b/drivers/net/phy/air_phy_lib.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2026 Airoha Technology Corp.
+ * Copyright (C) 2026 Collabora Ltd.
+ *                    Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#ifndef __AIR_PHY_LIB_H
+#define __AIR_PHY_LIB_H
+
+int air_phy_read_page(struct phy_device *phydev);
+int air_phy_write_page(struct phy_device *phydev, int page);
+
+#endif /* __AIR_PHY_LIB_H */

-- 
2.53.0



^ permalink raw reply related

* [PATCH net-next v2 1/4] dt-bindings: net: Add support for Airoha AN8801/R GbE PHY
From: Louis-Alexis Eyraud @ 2026-03-26 12:04 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Andrew Lunn, Heiner Kallweit,
	Russell King
  Cc: kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
	Louis-Alexis Eyraud
In-Reply-To: <20260326-add-airoha-an8801-support-v2-0-1a42d6b6050f@collabora.com>

From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>

Add a new binding to support the Airoha AN8801R Series Gigabit
Ethernet PHY.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 .../devicetree/bindings/net/airoha,an8801.yaml     | 85 ++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/airoha,an8801.yaml b/Documentation/devicetree/bindings/net/airoha,an8801.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b90b21b5505367309b5df8ece54ea38664f6b50f
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8801.yaml
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8801.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8801R Series PHY
+
+maintainers:
+  - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+description:
+  The Airoha AN8801R is a low power single-port Ethernet PHY Transceiver
+  with Single-port serdes interface for 1000Base-X/RGMII; this chip is
+  compliant with 10Base-T, 100Base-TX and 1000Base-T IEEE 802.3(u,ab)
+  and supports Energy Efficient Ethernet (802.3az), Full Duplex Control
+  Flow (802.3x), auto-negotiation, crossover detect and autocorrection,
+  Wake-on-LAN with Magic Packet, and Jumbo Frame up to 9 Kilobytes.
+  This PHY also supports up to three user-configurable LEDs, which are
+  usually used for LAN Activity, 100M, 1000M indication.
+
+allOf:
+  - $ref: ethernet-phy.yaml#
+
+properties:
+  compatible:
+    enum:
+      - ethernet-phy-idc0ff.0421
+
+  reg:
+    maxItems: 1
+
+  leds: true
+
+  wakeup-source:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enable Wake-on-LAN support
+
+required:
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/leds/common.h>
+
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ethernet-phy@0 {
+            compatible = "ethernet-phy-idc0ff.0421";
+            reg = <0>;
+
+            leds {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                led@0 {
+                    reg = <0>;
+                    color = <LED_COLOR_ID_GREEN>;
+                    function = LED_FUNCTION_LAN;
+                    default-state = "keep";
+                };
+
+                led@1 {
+                    reg = <1>;
+                    color = <LED_COLOR_ID_GREEN>;
+                    function = LED_FUNCTION_LAN;
+                    function-enumerator = <1>;
+                    default-state = "keep";
+                };
+
+                led@2 {
+                    reg = <2>;
+                    color = <LED_COLOR_ID_YELLOW>;
+                    function = LED_FUNCTION_LAN;
+                    function-enumerator = <2>;
+                    default-state = "keep";
+                };
+            };
+        };
+    };

-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH v6 1/5] mm: rmap: support batched checks of the references for large folios
From: Baolin Wang @ 2026-03-26 12:04 UTC (permalink / raw)
  To: Lorenzo Stoakes (Oracle)
  Cc: David Hildenbrand (Arm), Barry Song, akpm, catalin.marinas, will,
	lorenzo.stoakes, ryan.roberts, Liam.Howlett, vbabka, rppt, surenb,
	mhocko, riel, harry.yoo, jannh, willy, dev.jain, linux-mm,
	linux-arm-kernel, linux-kernel
In-Reply-To: <a0181a7c-d191-483d-bbc9-678bc355a984@lucifer.local>



On 3/26/26 7:10 PM, Lorenzo Stoakes (Oracle) wrote:
> On Thu, Mar 26, 2026 at 09:47:51AM +0800, Baolin Wang wrote:
>>
>>
>> On 3/25/26 11:06 PM, Lorenzo Stoakes (Oracle) wrote:
>>> On Wed, Mar 25, 2026 at 03:58:36PM +0100, David Hildenbrand (Arm) wrote:
>>>> On 3/25/26 15:36, Lorenzo Stoakes (Oracle) wrote:
>>>>> On Mon, Mar 16, 2026 at 03:15:18PM +0100, David Hildenbrand (Arm) wrote:
>>>>>> On 3/16/26 07:25, Baolin Wang wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Sure. However, after investigating RISC‑V and x86, I found that
>>>>>>> ptep_clear_flush_young() does not flush the TLB on these architectures:
>>>>>>>
>>>>>>> int ptep_clear_flush_young(struct vm_area_struct *vma,
>>>>>>>                  unsigned long address, pte_t *ptep)
>>>>>>> {
>>>>>>>       /*
>>>>>>>        * On x86 CPUs, clearing the accessed bit without a TLB flush
>>>>>>>        * doesn't cause data corruption. [ It could cause incorrect
>>>>>>>        * page aging and the (mistaken) reclaim of hot pages, but the
>>>>>>>        * chance of that should be relatively low. ]
>>>>>>>        *
>>>>>>>        * So as a performance optimization don't flush the TLB when
>>>>>>>        * clearing the accessed bit, it will eventually be flushed by
>>>>>>>        * a context switch or a VM operation anyway. [ In the rare
>>>>>>>        * event of it not getting flushed for a long time the delay
>>>>>>>        * shouldn't really matter because there's no real memory
>>>>>>>        * pressure for swapout to react to. ]
>>>>>>>        */
>>>>>>>       return ptep_test_and_clear_young(vma, address, ptep);
>>>>>>> }
>>>>>>
>>>>>> You'd probably want an arch helper then, that tells you whether
>>>>>> a flush_tlb_range() after ptep_test_and_clear_young() is required.
>>>>>>
>>>>>> Or some special flush_tlb_range() helper.
>>>>>>
>>>>>> I agree that it requires more work.
>>
>> (Sorry, David. I forgot to reply to your email because I've had a lot to
>> sort out recently.)
>>
>> Rather than adding more arch helpers (we already have plenty for the young
>> flag check), I think we should try removing the TLB flush, as I mentioned to
>> Barry[1]. MGLRU reclaim already skips the TLB flush, and it seems to work
>> fine. What do you think?
>>
>> Here are our previous attempts to remove the TLB flush:
>>
>> My patch: https://lkml.org/lkml/2023/10/24/533
>> Barry's patch:
>> https://lore.kernel.org/lkml/20220617070555.344368-1-21cnbao@gmail.com/
>>
>> [1] https://lore.kernel.org/all/6bdc4b03-9631-4717-a3fa-2785a7930aba@linux.alibaba.com/
>>
>>>>> Sorry unclear here - does the series need more work or does a follow up patch
>>>>> need more work?
>>>>
>>>> Follow up!
>>>
>>> Ok good as in mm-stable now. Sadly means I don't get to review it but there we
>>> go.
>>
>> Actually this patchset has already been merged upstream:)

Let me try to make things clear.

> Err but this revision was sent _during_ the merge window...?
> 
> Was sent on 9th Feb on Monday in merge window week 1, with a functional change
> listed:
> 
> - Skip batched unmapping for uffd case, reported by Dev. Thanks.
> 
> And then sent in 2nd batch on 18th Feb (see [0]).
> 
> So we were ok with 1 week of 'testing' (does anybody actually test -next during
> the merge window? Was it even sent to -next?) for what appears to be a
> functional change?

I posted v5 on Dec 26th[0], and it collected quite a few Reviewed-by 
tags and sat in mm-unstable for testing.

Later, Dev reported a uffd-related issue (I hope you recall that 
discussion). I posted a fix[1] for it on Jan 16th, which Andrew accepted.

Since then, the v5 series (plus the fix) continued to be tested in 
mm-unstable. We kept it there mainly because David mentioned he wanted 
to review the series, so we were waiting for his time.

On Feb 9th, after returning from vacation, David reviewed the series 
(thanks, David!). I replied to and addressed all his comments, then 
posted v6 on the same day[2].

Additionally, v6 had no functional changes compared to v5 + the fix, and 
it mainly addressed some coding style issues pointed out by David. I 
also discussed this with David off-list, and since there were no 
functional changes, my expectation was that it could still make it into 
the merge window. That is why v6 was merged.

[0] 
https://lore.kernel.org/linux-mm/cover.1766631066.git.baolin.wang@linux.alibaba.com/#t
[1] 
https://lore.kernel.org/linux-mm/20260116162652.176054-1-baolin.wang@linux.alibaba.com/
[2] 
https://lore.kernel.org/all/cover.1770645603.git.baolin.wang@linux.alibaba.com/

> And there was ongoing feedback on this and the v5 series (at [1])?

Regarding the feedback on v5, I believe everything has been addressed.

> This doesn't really feel sane?
> 
> And now I'm confused as to whether mm-stable patches can collect tags, since
> presumably this was in mm-stable at the point this respin was done?
> 
> Maybe I'm missing something here but this doesn't feel like a sane process?

Andrew, David, please correct me if I've missed anything. Also, please 
let me know if there's anything in the process that needs to be 
improved. Thanks.


^ permalink raw reply

* Re: [PATCH v11 03/22] drm: Add new general DRM property "color format"
From: Nicolas Frattaroli @ 2026-03-26 12:02 UTC (permalink / raw)
  To: Ville Syrjälä, Dave Stevenson
  Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan, kernel, amd-gfx, dri-devel,
	linux-kernel, linux-arm-kernel, linux-rockchip, intel-gfx,
	intel-xe, linux-doc, Werner Sembach, Andri Yngvason, Marius Vlad
In-Reply-To: <CAPY8ntCRPgN_ayHMGXFv9OrJrdyakUcUT0rvgY5J=FvdCFb6eA@mail.gmail.com>

On Thursday, 26 March 2026 12:16:12 Central European Standard Time Dave Stevenson wrote:
> On Wed, 25 Mar 2026 at 13:43, Ville Syrjälä
> <ville.syrjala@linux.intel.com> wrote:
> >
> > On Wed, Mar 25, 2026 at 12:49:19PM +0000, Dave Stevenson wrote:
> > > On Tue, 24 Mar 2026 at 16:02, Nicolas Frattaroli
> > > <nicolas.frattaroli@collabora.com> wrote:
> > > >
> > > > Add a new general DRM property named "color format" which can be used by
> > > > userspace to request the display driver to output a particular color
> > > > format.
> > > >
> > > > Possible options are:
> > > >     - auto (setup by default, driver internally picks the color format)
> > > >     - rgb
> > > >     - ycbcr444
> > > >     - ycbcr422
> > > >     - ycbcr420
> > > >
> > > > Drivers should advertise from this list which formats they support.
> > > > Together with this list and EDID data from the sink we should be able
> > > > to relay a list of usable color formats to users to pick from.
> > > >
> > > > Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
> > > > Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> > > > Co-developed-by: Andri Yngvason <andri@yngvason.is>
> > > > Signed-off-by: Andri Yngvason <andri@yngvason.is>
> > > > Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
> > > > Reviewed-by: Maxime Ripard <mripard@kernel.org>
> > > > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> > > > ---
> > > >  drivers/gpu/drm/drm_atomic_helper.c |   5 ++
> > > >  drivers/gpu/drm/drm_atomic_uapi.c   |  11 ++++
> > > >  drivers/gpu/drm/drm_connector.c     | 108 ++++++++++++++++++++++++++++++++++++
> > > >  include/drm/drm_connector.h         | 104 ++++++++++++++++++++++++++++++++++
> > > >  4 files changed, 228 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> > > > index 26953ed6b53e..b7753454b777 100644
> > > > --- a/drivers/gpu/drm/drm_atomic_helper.c
> > > > +++ b/drivers/gpu/drm/drm_atomic_helper.c
> > > > @@ -737,6 +737,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
> > > >                         if (old_connector_state->max_requested_bpc !=
> > > >                             new_connector_state->max_requested_bpc)
> > > >                                 new_crtc_state->connectors_changed = true;
> > > > +
> > > > +                       if (old_connector_state->color_format !=
> > > > +                           new_connector_state->color_format)
> > > > +                               new_crtc_state->connectors_changed = true;
> > > > +
> > > >                 }
> > > >
> > > >                 if (funcs->atomic_check)
> > > > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> > > > index 5bd5bf6661df..dee510c85e59 100644
> > > > --- a/drivers/gpu/drm/drm_atomic_uapi.c
> > > > +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> > > > @@ -935,6 +935,15 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
> > > >                 state->privacy_screen_sw_state = val;
> > > >         } else if (property == connector->broadcast_rgb_property) {
> > > >                 state->hdmi.broadcast_rgb = val;
> > > > +       } else if (property == connector->color_format_property) {
> > > > +               if (val > INT_MAX || !drm_connector_color_format_valid(val)) {
> > > > +                       drm_dbg_atomic(connector->dev,
> > > > +                                      "[CONNECTOR:%d:%s] unknown color format %llu\n",
> > > > +                                      connector->base.id, connector->name, val);
> > > > +                       return -EINVAL;
> > > > +               }
> > > > +
> > > > +               state->color_format = val;
> > > >         } else if (connector->funcs->atomic_set_property) {
> > > >                 return connector->funcs->atomic_set_property(connector,
> > > >                                 state, property, val);
> > > > @@ -1020,6 +1029,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
> > > >                 *val = state->privacy_screen_sw_state;
> > > >         } else if (property == connector->broadcast_rgb_property) {
> > > >                 *val = state->hdmi.broadcast_rgb;
> > > > +       } else if (property == connector->color_format_property) {
> > > > +               *val = state->color_format;
> > > >         } else if (connector->funcs->atomic_get_property) {
> > > >                 return connector->funcs->atomic_get_property(connector,
> > > >                                 state, property, val);
> > > > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> > > > index 47dc53c4a738..e848374dee0b 100644
> > > > --- a/drivers/gpu/drm/drm_connector.c
> > > > +++ b/drivers/gpu/drm/drm_connector.c
> > > > @@ -1388,6 +1388,18 @@ static const u32 hdmi_colorspaces =
> > > >         BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
> > > >         BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER);
> > > >
> > > > +static const u32 hdmi_colorformats =
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
> > > > +
> > > > +static const u32 dp_colorformats =
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
> > > > +       BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
> > > > +
> > > >  /*
> > > >   * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry
> > > >   * Format Table 2-120
> > > > @@ -2940,6 +2952,102 @@ int drm_connector_attach_colorspace_property(struct drm_connector *connector)
> > > >  }
> > > >  EXPORT_SYMBOL(drm_connector_attach_colorspace_property);
> > > >
> > > > +/**
> > > > + * drm_connector_attach_color_format_property - create and attach color format property
> > > > + * @connector: connector to create the color format property on
> > > > + * @supported_color_formats: bitmask of bit-shifted &enum drm_output_color_format
> > > > + *                           values the connector supports
> > > > + *
> > > > + * Called by a driver to create a color format property. The property is
> > > > + * attached to the connector automatically on success.
> > > > + *
> > > > + * @supported_color_formats should only include color formats the connector
> > > > + * type can actually support.
> > > > + *
> > > > + * Returns:
> > > > + * 0 on success, negative errno on error
> > > > + */
> > > > +int drm_connector_attach_color_format_property(struct drm_connector *connector,
> > > > +                                              unsigned long supported_color_formats)
> > > > +{
> > > > +       struct drm_device *dev = connector->dev;
> > > > +       struct drm_prop_enum_list enum_list[DRM_CONNECTOR_COLOR_FORMAT_COUNT];
> > > > +       unsigned int i = 0;
> > > > +       unsigned long fmt;
> > > > +
> > > > +       if (connector->color_format_property)
> > > > +               return 0;
> > > > +
> > > > +       if (!supported_color_formats) {
> > > > +               drm_err(dev, "No supported color formats provided on [CONNECTOR:%d:%s]\n",
> > > > +                       connector->base.id, connector->name);
> > > > +               return -EINVAL;
> > > > +       }
> > > > +
> > > > +       if (supported_color_formats & ~GENMASK(DRM_OUTPUT_COLOR_FORMAT_COUNT - 1, 0)) {
> > > > +               drm_err(dev, "Unknown color formats provided on [CONNECTOR:%d:%s]\n",
> > > > +                       connector->base.id, connector->name);
> > > > +               return -EINVAL;
> > > > +       }
> > > > +
> > > > +       switch (connector->connector_type) {
> > > > +       case DRM_MODE_CONNECTOR_HDMIA:
> > > > +       case DRM_MODE_CONNECTOR_HDMIB:
> > > > +               if (supported_color_formats & ~hdmi_colorformats) {
> > > > +                       drm_err(dev, "Color formats not allowed for HDMI on [CONNECTOR:%d:%s]\n",
> > > > +                               connector->base.id, connector->name);
> > > > +                       return -EINVAL;
> > > > +               }
> > > > +               break;
> > > > +       case DRM_MODE_CONNECTOR_DisplayPort:
> > > > +       case DRM_MODE_CONNECTOR_eDP:
> > > > +               if (supported_color_formats & ~dp_colorformats) {
> > > > +                       drm_err(dev, "Color formats not allowed for DP on [CONNECTOR:%d:%s]\n",
> > > > +                               connector->base.id, connector->name);
> > > > +                       return -EINVAL;
> > > > +               }
> > > > +               break;
> > > > +       }
> > > > +
> > > > +       enum_list[0].name = "AUTO";
> > > > +       enum_list[0].type = DRM_CONNECTOR_COLOR_FORMAT_AUTO;
> > > > +
> > > > +       for_each_set_bit(fmt, &supported_color_formats, DRM_OUTPUT_COLOR_FORMAT_COUNT) {
> > > > +               switch (fmt) {
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_RGB444:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
> > > > +                       break;
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
> > > > +                       break;
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR422;
> > > > +                       break;
> > > > +               case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
> > > > +                       enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
> > > > +                       break;
> > > > +               default:
> > > > +                       drm_warn(dev, "Unknown supported format %ld on [CONNECTOR:%d:%s]\n",
> > > > +                                fmt, connector->base.id, connector->name);
> > > > +                       continue;
> > > > +               }
> > > > +               enum_list[i].name = drm_hdmi_connector_get_output_format_name(fmt);
> > > > +       }
> > > > +
> > > > +       connector->color_format_property =
> > > > +               drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "color format",
> > > > +                                        enum_list, i + 1);
> > > > +
> > > > +       if (!connector->color_format_property)
> > > > +               return -ENOMEM;
> > > > +
> > > > +       drm_object_attach_property(&connector->base, connector->color_format_property,
> > > > +                                  DRM_CONNECTOR_COLOR_FORMAT_AUTO);
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +EXPORT_SYMBOL(drm_connector_attach_color_format_property);
> > > > +
> > > >  /**
> > > >   * drm_connector_atomic_hdr_metadata_equal - checks if the hdr metadata changed
> > > >   * @old_state: old connector state to compare
> > > > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > > > index af8b92d2d5b7..bd549f912b76 100644
> > > > --- a/include/drm/drm_connector.h
> > > > +++ b/include/drm/drm_connector.h
> > > > @@ -571,14 +571,102 @@ enum drm_colorspace {
> > > >   *   YCbCr 4:2:2 output format (ie. with horizontal subsampling)
> > > >   * @DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
> > > >   *   YCbCr 4:2:0 output format (ie. with horizontal and vertical subsampling)
> > > > + * @DRM_OUTPUT_COLOR_FORMAT_COUNT:
> > > > + *   Number of valid output color format values in this enum
> > > >   */
> > > >  enum drm_output_color_format {
> > > >         DRM_OUTPUT_COLOR_FORMAT_RGB444 = 0,
> > > >         DRM_OUTPUT_COLOR_FORMAT_YCBCR444,
> > > >         DRM_OUTPUT_COLOR_FORMAT_YCBCR422,
> > > >         DRM_OUTPUT_COLOR_FORMAT_YCBCR420,
> > > > +       DRM_OUTPUT_COLOR_FORMAT_COUNT,
> > > >  };
> > > >
> > > > +/**
> > > > + * enum drm_connector_color_format - Connector Color Format Request
> > > > + *
> > > > + * This enum, unlike &enum drm_output_color_format, is used to specify requests
> > > > + * for a specific color format on a connector through the DRM "color format"
> > > > + * property. The difference is that it has an "AUTO" value to specify that
> > > > + * no specific choice has been made.
> > > > + */
> > > > +enum drm_connector_color_format {
> > > > +       /**
> > > > +        * @DRM_CONNECTOR_COLOR_FORMAT_AUTO: The driver or display protocol
> > > > +        * helpers should pick a suitable color format. All implementations of a
> > > > +        * specific display protocol must behave the same way with "AUTO", but
> > > > +        * different display protocols do not necessarily have the same "AUTO"
> > > > +        * semantics.
> > > > +        *
> > > > +        * For HDMI, "AUTO" picks RGB, but falls back to YCbCr 4:2:0 if the
> > > > +        * bandwidth required for full-scale RGB is not available, or the mode
> > > > +        * is YCbCr 4:2:0-only, as long as the mode and output both support
> > > > +        * YCbCr 4:2:0.
> > >
> > > Is there a reason you propose dropping back to YCbCr 4:2:0 without
> > > trying YCbCr 4:2:2 first? Minimising the subsampling is surely
> > > beneficial, and vc4 for one can do 4:2:2 but not 4:2:0.
> >
> > On HDMI 4:2:2 is always 12bpc, so it doesn't save any bandwidth
> > compared to 8bpc 4:4:4.
> 
> It does save bandwidth against 10 or 12bpc RGB 4:4:4.
> 
> Or is the implication that max_bpc = 12 and
> DRM_CONNECTOR_COLOR_FORMAT_AUTO should drop bpc down to 8 and select
> RGB in preference to selecting 4:2:2?

Yes. Some people consider max-bpc to not be a legitimate way of requesting
an actual bpc, and don't think drivers will choose the highest bpc <= max-bpc,
and instead may negotiate a fantasy number anywhere below or equal to max-bpc.

Of course this logic could be done in userspace which knows whether the
less chroma for more bit depth trade-off is worth it, but userspace does
not know the negotiated link bpc, and my attempts at adding a property for
it are being blocked.

> 
>   Dave
> 
> > --
> > Ville Syrjälä
> > Intel
> 






^ permalink raw reply

* Re: (subset) [PATCH v2 4/9] leds: Kconfig: drop unneeded dependency on OF_GPIO
From: Lee Jones @ 2026-03-26 12:03 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Andrew Lunn, Heiner Kallweit,
	Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Linus Walleij, Lee Jones, Pavel Machek,
	Wim Van Sebroeck, Guenter Roeck, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Sebastian Reichel, Bartosz Golaszewski
  Cc: brgl, linux-arm-kernel, linux-kernel, netdev, linux-gpio,
	linux-leds, linux-watchdog, linux-media, linux-staging, linux-pm
In-Reply-To: <20260316-gpio-of-kconfig-v2-4-de2f4b00a0e4@oss.qualcomm.com>

On Mon, 16 Mar 2026 10:45:24 +0100, Bartosz Golaszewski wrote:
> OF_GPIO is selected automatically on all OF systems. Any symbols it
> controls also provide stubs so there's really no reason to select it
> explicitly.

Applied, thanks!

[4/9] leds: Kconfig: drop unneeded dependency on OF_GPIO
      commit: b727ba2560a8a806680b45c9acc5a49bc39b8e43

--
Lee Jones [李琼斯]



^ permalink raw reply

* Re: [PATCH v9 2/5] i2c: mux: add support for per channel bus frequency
From: Marcus Folkesson @ 2026-03-26 11:39 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Wolfram Sang, Peter Rosin, Michael Hennerich, Bartosz Golaszewski,
	Andi Shyti, Bartosz Golaszewski, linux-i2c, linux-kernel,
	linux-arm-kernel
In-Reply-To: <acKbYhbwZzv2gTnB@ashevche-desk.local>

On Tue, Mar 24, 2026 at 04:10:42PM +0200, Andy Shevchenko wrote:

[...]
> 
> ...
> 
> > +		of_property_read_u32(child, "clock-frequency", &priv->adap.clock_hz);
> 
> Wondering if we may use existing API to get i2c timings from fw description?
> i2c_parse_fw_timings() (it might be that it needs to be split for pure fwnode
> one and device wrapped).

I like the idea, even if I don't see that many other parts of the
kernel will be using it.

After this patchset, I intend to make all other bus drivers use
i2c_parse_fw_timings() for fetching their clock frequency. I will
investigate the splitup in the scope of that series.

> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 

Best regards,
Marcus Folkesson


^ permalink raw reply

* Re: [PATCH v4] arm64: dts: lx2160a: extend 32-bit, and add 16 & 64-bit pci regions
From: Josua Mayer @ 2026-03-26 11:26 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel@lists.infradead.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260302-lx2160-pci-v4-1-30a30dc47ec6@solid-run.com>

Hi all,

This patch has never received a reply in versions v1, v2, v3 nor v4.
Is it on the wrong list? Should I be adding pci list?

Am 02.03.26 um 15:35 schrieb Josua Mayer:
> LX2160 SoC pci-e controller supports 64-bit memory regions up to 16GB,
> 32-bit regions up to 3GB and 16-bit regions up to 64k.
>
> For each pci-e controller:
> - extend the existing 32-bit regions to 3GB size
> - add 16-bit region
> - add 64-bit region
> See [1] amd [2] for boot messages showing ranges before and after.
>
> The 64-bit area flags are very particular:
> - IORESOURCE_AUTO: ensures of_bus_pci_get_flags sets prefetch flag
>   (avoids "Memory resource size exceeds max for 32 bits" error during
>    boot, generated by pci_parse_request_of_pci_ranges)
> - IORESOURCE_SYSRAM_DRIVER_MANAGED: ensures IORESOURCE_MEM flag is not
>   cleared, as required by devm_of_pci_get_host_bridge_resources to print
>   correct resource type during boot:
>   MEM 0xa700000000..0xa7ffffffff -> 0xa700000000 (with this flag)
>   err 0xa700000000..0xa7ffffffff -> 0xa700000000 (without)
> - IORESOURCE_MEM_64: pci address space is 64-bit
> - IORESOURCE_PREFETCH: is prefetchable
> - IORESOURCE_MEM: is memory (set implicitly when omitted in dts)
>
> IORESOURCE_BUSY is dropped since it has no effect when specified in dts.
>
> The 16GB 64-bit area is split into 4 pieces because the layerscape pcie
> driver fails to program atu for larger ranges [3].
>
> The range for 16-bit io window was defined by Jon Nettleton, and
> includes flag IORESOURCE_EXT_TYPE_BITS to support multiport io cards.
>
> Similar memory allocation with similar flags was tested with UEFI and ACPI
> on pcie3 and pcie5.
>
> This specific set of ranges was tested with nxp bsp versions lsdk-21.08,
> ls-5.15.71-2.2.0, ls-6.6.52-2.2.0, Debian 13 (v6.12.41), mainline v7.0-rc2,
> using u-boot:
> - pcie5 with a Radeon Pro WX2100 with Gnome Desktop
> - pcie3 with an ADATA NVME
>
> This fixes allocation of large, and 64-bit BARs as requested by many pci
> cards - especially graphics processors or AI accelerators, e.g.:
>
> [    2.941187] pci 0000:01:00.0: BAR 0: no space for [mem size 0x200000000 64bit pref]
> [    2.948834] pci 0000:01:00.0: BAR 0: failed to assign [mem size 0x200000000 64bit pref]
>
> [1] example of new allocations (pcie5):
> [    1.716942] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    1.724261] layerscape-pcie 3800000.pcie:      MEM 0xa700000000..0xa7ffffffff -> 0xa700000000
> [    1.732795] layerscape-pcie 3800000.pcie:      MEM 0xa600000000..0xa6ffffffff -> 0xa600000000
> [    1.741325] layerscape-pcie 3800000.pcie:      MEM 0xa500000000..0xa5ffffffff -> 0xa500000000
> [    1.749861] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa4ffffffff -> 0xa400000000
> [    1.758389] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
> [    1.766915] layerscape-pcie 3800000.pcie:       IO 0xa010000000..0xa01000ffff -> 0x0000000000
> [    1.776141] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
> [    1.880382] layerscape-pcie 3800000.pcie: PCIe Gen.3 x8 link up
> [    1.886349] layerscape-pcie 3800000.pcie: PCI host bridge to bus 0001:00
> [    1.893046] pci_bus 0001:00: root bus resource [bus 00-ff]
> [    1.898525] pci_bus 0001:00: root bus resource [mem 0xa700000000-0xa7ffffffff pref]
> [    1.906174] pci_bus 0001:00: root bus resource [mem 0xa600000000-0xa6ffffffff pref]
> [    1.913822] pci_bus 0001:00: root bus resource [mem 0xa500000000-0xa5ffffffff pref]
> [    1.921471] pci_bus 0001:00: root bus resource [mem 0xa400000000-0xa4ffffffff pref]
> [    1.929120] pci_bus 0001:00: root bus resource [mem 0xa040000000-0xa0ffffffff] (bus address [0x40000000-0xffffffff])
> [    1.939633] pci_bus 0001:00: root bus resource [io  0x0000-0xffff]
> [    1.945824] pci 0001:00:00.0: [1957:8d80] type 01 class 0x060400 PCIe Root Port
> [    1.953146] pci 0001:00:00.0: PCI bridge to [bus 01-ff]
> [    1.958369] pci 0001:00:00.0:   bridge window [io  0x1000-0x1fff]
> [    1.964456] pci 0001:00:00.0:   bridge window [mem 0xa040000000-0xa0502fffff]
>
> [2] example of previous allocations (pcie5):
> [    1.716744] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    1.724060] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa07fffffff -> 0x0040000000
> [    1.733277] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
> [    1.836220] layerscape-pcie 3800000.pcie: PCIe Gen.3 x8 link up
> [    1.842186] layerscape-pcie 3800000.pcie: PCI host bridge to bus 0001:00
> [    1.848883] pci_bus 0001:00: root bus resource [bus 00-ff]
> [    1.854363] pci_bus 0001:00: root bus resource [mem 0xa040000000-0xa07fffffff] (bus address [0x40000000-0x7fffffff])
> [    1.864892] pci 0001:00:00.0: [1957:8d80] type 01 class 0x060400 PCIe Root Port
> [    1.872216] pci 0001:00:00.0: PCI bridge to [bus 01-ff]
> [    1.877438] pci 0001:00:00.0:   bridge window [io  0x1000-0x1fff]
> [    1.883526] pci 0001:00:00.0:   bridge window [mem 0xa040000000-0xa0502fffff]
>
> [3] error programming atu beyond 4GB:
> [    1.716762] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    1.724080] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
> [    1.732615] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
> [    1.741142] layerscape-pcie 3800000.pcie:       IO 0xa010000000..0xa01000ffff -> 0x0000000000
> [    1.750379] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
> [    1.759089] layerscape-pcie 3800000.pcie: Failed to set MEM range [mem 0xa400000000-0xa7ffffffff flags 0x2200]
> [    1.769089] layerscape-pcie 3800000.pcie: probe with driver layerscape-pcie failed with error -22
>
> Signed-off-by: Josua Mayer <josua@solid-run.com>
> ---
> Changes in v4
> - dropped accidentally added empty line at top of file:
> - actually drop RFC prefix
> - rebased on v7.0-rc1 and re-tested on v7.0-rc2
> - Link to v3: https://lore.kernel.org/r/20250907-lx2160-pci-v3-1-bb66cc41b8f9@solid-run.com
>
> Changes in v3:
> - dropped rfc label
> - adjusted flags
> - split 16GB area into 4x4GB sections.
> - enhance commit description with details explanation
> - Link to v2: https://lore.kernel.org/r/20240429-lx2160-pci-v2-1-1b94576d6263@solid-run.com
>
> Changes in v2:
> - adjusted flags to fix several errors during probe and bar allocation
> - explicitly tested with 2 pci cards on Debian (Linux 6.1)
> - still rfc because a limitation in designware pci driver
> - Link to v1: https://lore.kernel.org/r/20240321-lx2160-pci-v1-1-3673708f7eb6@solid-run.com
> ---
>  arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 42 ++++++++++++++++++++++----
>  1 file changed, 36 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> index 853b01452813a..5b48de0c853a8 100644
> --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> @@ -1185,7 +1185,12 @@ pcie1: pcie@3400000 {
>  			apio-wins = <8>;
>  			ppio-wins = <8>;
>  			bus-range = <0x0 0xff>;
> -			ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> +			ranges = <0x42102200 0x87 0x00000000 0x87 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x86 0x00000000 0x86 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x85 0x00000000 0x85 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x84 0x00000000 0x84 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x02000200 0x00 0x40000000 0x80 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +				 <0x01200100 0x00 0x00000000 0x80 0x10000000 0x00 0x00010000>; /* 16-Bit IO Window */
>  			msi-parent = <&its 0>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 7>;
> @@ -1213,7 +1218,12 @@ pcie2: pcie@3500000 {
>  			apio-wins = <8>;
>  			ppio-wins = <8>;
>  			bus-range = <0x0 0xff>;
> -			ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> +			ranges = <0x42102200 0x8f 0x00000000 0x8f 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x8e 0x00000000 0x8e 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x8d 0x00000000 0x8d 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x8c 0x00000000 0x8c 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x02000200 0x00 0x40000000 0x88 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +				 <0x01200100 0x00 0x00000000 0x88 0x10000000 0x00 0x00010000>; /* 16-Bit IO Window */
>  			msi-parent = <&its 0>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 7>;
> @@ -1241,7 +1251,12 @@ pcie3: pcie@3600000 {
>  			apio-wins = <256>;
>  			ppio-wins = <24>;
>  			bus-range = <0x0 0xff>;
> -			ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> +			ranges = <0x42102200 0x97 0x00000000 0x97 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x96 0x00000000 0x96 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x95 0x00000000 0x95 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x94 0x00000000 0x94 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x02000200 0x00 0x40000000 0x90 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +				 <0x01200100 0x00 0x00000000 0x90 0x10000000 0x00 0x00010000>; /* 16-Bit IO Window */
>  			msi-parent = <&its 0>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 7>;
> @@ -1269,7 +1284,12 @@ pcie4: pcie@3700000 {
>  			apio-wins = <8>;
>  			ppio-wins = <8>;
>  			bus-range = <0x0 0xff>;
> -			ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> +			ranges = <0x42102200 0x9f 0x00000000 0x9f 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x9e 0x00000000 0x9e 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x9d 0x00000000 0x9d 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0x9c 0x00000000 0x9c 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x02000200 0x00 0x40000000 0x98 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +				 <0x01200100 0x00 0x00000000 0x98 0x10000000 0x00 0x00010000>; /* 16-Bit IO Window */
>  			msi-parent = <&its 0>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 7>;
> @@ -1297,7 +1317,12 @@ pcie5: pcie@3800000 {
>  			apio-wins = <256>;
>  			ppio-wins = <24>;
>  			bus-range = <0x0 0xff>;
> -			ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> +			ranges = <0x42102200 0xa7 0x00000000 0xa7 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0xa6 0x00000000 0xa6 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0xa5 0x00000000 0xa5 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0xa4 0x00000000 0xa4 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x02000200 0x00 0x40000000 0xa0 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +				 <0x01200100 0x00 0x00000000 0xa0 0x10000000 0x00 0x00010000>; /* 16-Bit IO Window */
>  			msi-parent = <&its 0>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 7>;
> @@ -1325,7 +1350,12 @@ pcie6: pcie@3900000 {
>  			apio-wins = <8>;
>  			ppio-wins = <8>;
>  			bus-range = <0x0 0xff>;
> -			ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> +			ranges = <0x42102200 0xaf 0x00000000 0xaf 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0xae 0x00000000 0xae 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0xad 0x00000000 0xad 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x42102200 0xac 0x00000000 0xac 0x00000000 0x01 0x00000000>, /* 64-Bit - prefetchable - 4GB chunk */
> +				 <0x02000200 0x00 0x40000000 0xa8 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +				 <0x01200100 0x00 0x00000000 0xa8 0x10000000 0x00 0x00010000>; /* 16-Bit IO Window */
>  			msi-parent = <&its 0>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 7>;
>
> ---
> base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
> change-id: 20240118-lx2160-pci-4bdb196e58f3
>
> Best regards,
- Josua Mayer

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox